Как создать изображение BytesIO и перейти к шаблону

ЦЕЛЬ

Я пытаюсь:

  1. Создайте гистограмму,
  2. Сохраните временную память,
  3. Передайте изображение в шаблон.

У меня возникли проблемы с шагом 3 выше. Я подозреваю, что совершаю простую и фундаментальную ошибку в отношении передачи данных context в шаблон.

ОШИБКА

HTML отображается с неработающим тегом изображения.

КОД

Views.py

class SearchResultsView(DetailView):

   ...

   def get(self, request, *args, **kwargs):
        self.get_histogram(request)
        return super(SearchResultsView, self).get(request, *args, **kwargs)


    def get_context_data(self, **kwargs):
        context = super(SearchResultsView, self).get_context_data(**kwargs)
        return context


    def get_histogram(self, request):
        """ Function to create and save histogram of Hashtag.locations """
        # create the histogram
        plt.show()
        img_in_memory = BytesIO()
        plt.savefig(img_in_memory, format="png")
        image = base64.b64encode(img_in_memory.getvalue())
        context = {'image':image}
        return context

Результаты.html

<img src="data:image/png;base64,{{image}}" alt="Location Histogram" />

РЕШЕНИЕ

В дополнение к проблемам с get и get_context_data, как описано @ruddra ниже, еще одна проблема заключалась в том, что мне пришлось декодировать строку base64 как строку Unicode. Для получения дополнительной информации см. здесь.

Для этого я включил: image = image.decode('utf8')

Итак, views.py выглядит так:

def get_histogram(self, request):
    # draw histogram
    plt.show()
    img_in_memory = BytesIO()
    plt.savefig(img_in_memory, format="png") # save the image in memory using BytesIO
    img_in_memory.seek(0) # rewind to beginning of file
    image = base64.b64encode(img_in_memory.getvalue()) # load the bytes in the context as base64
    image = image.decode('utf8')
    return {'image':image}

person Darcy    schedule 03.11.2018    source источник


Ответы (1)


Вы неправильно вызываете get_histogram. Вы можете сделать это следующим образом:

class SearchResultsView(DetailsView):
    ...

    def get_context_data(self, **kwargs):
         context = super(SearchResultsView, self).get_context_data(**kwargs)
         context.update(self.get_histogram(self.request))
         return context

Вам не нужно вызывать метод get_histogram в get или переопределять метод get.

Обновлять

Я пробовал так:

 class SearchResultsView(DetailsView):
     ...

     def get_histogram(self):
         x = 2
         y = 3
         z = 2
         t= 3    
         plt.plot(x, y)
         plt.plot(z, t)
         plt.show()
         img_in_memory = io.BytesIO()  # for Python 3
         plt.savefig(img_in_memory, format="png")
         image = base64.b64encode(img_in_memory.getvalue())
         return {'image':image}

     def get_context_data(self, *args, **kwargs):
         context = super(SearchResultsView, self).get_context_data(*args, **kwargs)
         context.update(self.get_histogram())
         return context

Вывод выглядит следующим образом: введите здесь описание изображения

person ruddra    schedule 03.11.2018
comment
Спасибо, @ruddra, я исправил get, как советовали. Однако results.html все еще отображается с поврежденным тегом изображения, где, как я ожидаю, будет гистограмма! - person Darcy; 04.11.2018
comment
@ycrad Я добавил, как написал код. Пожалуйста, посмотрите. - person ruddra; 04.11.2018
comment
К сожалению, это все еще не работает; поврежденное HTML-изображение все еще загружается. Поскольку это работает для примера, который вы опубликовали, теперь я знаю, что моя ошибка должна быть где-то еще в коде. Если это поможет, я включил ссылку на репо в запросе выше. - person Darcy; 08.11.2018
comment
Извините, возможно, я не смогу помочь вам с вашим репозиторием, но я могу помочь вам отладить проблему. В шаблонах просто вставьте где-нибудь {{image}} без тегов и проверьте, не проходит ли что-то через контекст. Если вы ничего не получите, в этом случае могут возникнуть проблемы с генерацией изображения. - person ruddra; 08.11.2018
comment
Если я сделаю так, как вы предлагаете, будет возвращена закодированная строка base64. - person Darcy; 08.11.2018
comment
Это означает, что вы можете отправлять данные из представления в шаблон, но проблема заключается в другом, возможно, в построении графика. - person ruddra; 08.11.2018
comment
Спасибо @ruddra, я не верю, что дело в графике, так как я использовал ваш пример графика, и он все еще не работает. Вместо этого я теперь подозреваю, что проблема может быть вызвана тем, что «styles.css» загружается неправильно. В любом случае, я уверен, что это выходит за рамки исходного запроса, поэтому пометил ваш ответ как принятый. - person Darcy; 09.11.2018
comment
Просто чтобы вы знали, я включил решение в запрос @ruddra, еще раз спасибо :) - person Darcy; 09.11.2018