У меня есть изображение морского барплота, которое я хотел бы отобразить внутри шаблона django.
Я рассмотрел несколько решений, и мне удалось отобразить изображение с помощью HttpResponse. Однако изображение, которое он отображает, — это всего лишь изображение. То, что я хочу, это изображение сюжета на веб-странице, и вы все равно можете щелкнуть панель навигации, кнопку «Домой» и т. д.
import seaborn as sns
import matplotlib.pyplot as plt
from matplotlib.backends.backend_agg import FigureCanvasAgg
from io import BytesIO
from django.template.loader import render_to_string
В views.py
def top_causal(request):
# code for data manipulation
f = plt.figure(figsize=(10, 5))
ax = sns.barplot(data)
# labels, title etc...
FigureCanvasAgg(f)
buf = BytesIO()
plt.savefig(buf, format='png)
plt.close(f)
# this works
response = HttpResponse(buf.getvalue(), content_type='image/png')
return response
# What I want which is to display the image inside a template(does not work)
buffer = buf.getvalue()
content_type = "image/png"
graphic = (buffer, content_type)
rendered = render_to_string('top_causal.html', {'graphic': graphic})
return HttpResponse(rendered)
в top_causal.html
<img src = "data:image/png;base64,{{ graphic|safe }}" alt = "Not working.">
HttpResponse отображает изображение как страницу.
Ответ с использованием render_to_string возвращает это вместо изображения внутри веб-страницы. Я все еще вижу панель навигации.
\x06\x1d\x00\x80kT\xb7n]eee\x95\x18\xff\xe1\x87\x1f$I\xf5\xea\xd5\xb3\x19\xcf\xce\xce.\x11\x9b\x9d\x9d-WWW999U\xb8~\xa7N\x9d$\xfd\xf6\x02\xb2\xb0\xb00IR\x9b6mt\xe4\xc8\x91\x12\xb1G\x8e\x1c\x91\xc5b\xb9\xea\xe7\xe1\xda\xb5k\xa7\xf7\xdf\x7f_\xc5\xc5\xc5:|\xf8\xb0V\xadZ\xa5\xe7\x9f\x7f^\xb5j\xd5\xd2\xd4\xa9S\xafx\xee\xdbo\xbf\xad\x81\x03\x07j\xc9\x92%6\xe3\xb9\xb9\xb9\xe5\xba\x9e\xbau\xeb\xcab\xb1h\xc2\x84\t\x9a0aB\xa91M\x9b6-W\xae\xab\xa9W\xaf\x9e\xaaU\xab\xa6\xbd{\xf7\xaaj\xd5\xaa%\xe6]\\\\\xecR\xe7\xb2;\xef\xbcSqqq\x92~{Q\xde\xbb\xef\xbe\xaby\xf3\xe6\xa9\xb8\xb8X\x8b\x16-\xb2k-\x00\x80\xe3b\x07\x1d\x00\x80k\xd4\xb7o_\xa5\xa4\xa4\x94x\x13w||\xbc\xaaT\xa9\xa2\x90\x90\x10\x9b\xf1\xf7\xdf\x7f\xdfz\x8b\xb5$\x9d;wN[\xb7n-\x11W^\x97o\x8do\xd6\xac\x99ul\xc8\x90!JIIQJJ\x8au\xec\xd7 ...





Вам нужно преобразовать изображение в массив байтов, закодировать его в base64 и встроить в свой шаблон. Вот как это сделать:
<!DOCTYPE html>
<!--my_template.html-->
<html>
<div class='section'>
<div class='flex column plot mt15 mlr15 justify-left align-left'>
<img src='{{ imuri }}'/>
</div>
</div>
</html>
from django.template.loader import get_template
def top_causal(request):
# .......................
# Get your plot ready ...
# .......................
figure = plt.gcf()
buf = io.BytesIO()
figure.savefig(buf, format='png', transparent=True, quality=100, dpi=200)
buf.seek(0)
imsrc = base64.b64encode(buf.read())
imuri = 'data:image/png;base64,{}'.format(urllib.parse.quote(imsrc))
context = { 'plot': imuri}
# Now embed that to your template
template = get_template('my_template.html')
html = template.render(context=context)
# Your template is ready to go...
Конечно, остальное — это то, что вы делаете, когда рендерите обычный шаблон django, я просто хотел показать суть.
Я изменил коды так, как они выглядят, но изображение все еще не появляется. Предупреждения, которые я получил, были WARNING: QApplication was not created in the main() thread. и QObject::~QObject: Timers cannot be stopped from another thread, которые появляются в моем командном окне, но веб-сайт все еще работает в обычном режиме. Означает ли это, что мне нужно перезапустить и запустить снова?
Что ж, проблема, с которой вы столкнулись, заключается в том, что matplotlib использует tkinter, который должен работать в основном потоке. Поэтому, если вы рисуете свое изображение в основном потоке или используете многопроцессорные библиотеки заданий, такие как сельдерей и т. д., Это будет работать.
Мой сервер использует Agg. Как мне перейти в основной поток и построить там сюжет?
Если вы получаете предупреждение QApplication was not created in the main() thread., вы фактически не используете серверную часть agg. Возможно, это тема для нового вопроса, но убедитесь, что matplotlib.use("Agg") поверх кода, прежде чем импортировать pyplot.
Я отказался от идеи использовать matplotlib и вместо этого использовал Highcharts https://www.highcharts.com/, чтобы построить свой график и отобразить его на веб-странице.
Отображаемые данные были получены с использованием Django ORM и Query API.
Мне все еще нужно добавить
return render(request, 'top_causal.html', context)в конце функции?