0

I've been looking for and trying out quite some solutions for this problem (here, here and many more) but I'm still not able to fix this.

So, I'm using PDFViewMixin to export a template as a PDF:

from django.views.generic.detail import TemplateResponseMixin

class ExportViewMixin(TemplateResponseMixin):
    filename = None
    content_type = 'text/html'

    def get_filename(self):
        return self.filename

    def get_content_type(self):
        return self.content_type

    def document_to_response(self, response, context=None):
        raise NotImplementedError('Subclasses must implement this method')

    def render_to_response(self, context, **kwargs):
        response = HttpResponse(content_type=self.get_content_type())
        response['Content-Disposition'] = 'attachment;filename="%s"' % self.get_filename()
        self.document_to_response(response, context=context)
        return response

 class PDFViewMixin(ExportViewMixin):
   '''Generic view that render a template into a PDF 
   and return it as response content.
   '''
   content_type = 'application/pdf'

   def gen_pdf(self, context):
       template = get_template(self.template_name)
       # need absolute_uris to correctly get static files
       try:
           html_doc = HTML(string=template.render(Context(context)), base_url=context.get('base_url'))
       except TypeError:       # Django>=1.11
           html_doc = HTML(string=template.render(context), base_url=context.get('base_url'))
       return html_doc.render()

   def document_to_response(self, response, context=None):
       self.gen_pdf(context).write_pdf(response)

   def get_context_data(self, **context):
       context = super(PDFViewMixin, self).get_context_data(**context)
       context['base_url'] = self.request.build_absolute_uri()
       context['content_type'] = self.get_content_type()
       return context

The view that controls the template inherits from PDFViewMixin and django DetailView. In the template I try to render the model's ImageField as follows (which perfectly works before exporting it):

{% if object.image %}
   <img src="{{ object.image.url }}">
{% endif %}

I believe (as pointed out here) the problem to be that the render_to_response acts like AnonymousUser and white it tries to fetch the image through login, gets an error. Indeed, this is the requests log I get in the console:

[27/Feb/2019 11:05:10] "GET /login/?next=/media/images/0013/765-default-avatar.png HTTP/1.1" 200 3379
WARNING: Failed to load image at "http://localhost:8000/media/images/0013/765-default-avatar.png" (Pixbuf error: Unrecognized image file format)

I've tried setting up a custom photo_url_fetcher (like this), using absolute uri but with no results. Does someone have a working solution for this problem?

gccallie
  • 107
  • 15

1 Answers1

0

After various attempts I found this solution:

  • Add a method to get the image's path in the model

    def get_image_path(self):
        if image:
            return os.path.join(settings.MEDIA_ROOT, self.image.path)
        return ''
    
  • Prepend file:// to the path in the template

    <img src="file://{{ obj.get_image_path }}">

gccallie
  • 107
  • 15