Image not showing in pdf generated with weasyprint

I have an app that allows you to upload an image and I need to generate a pdf with that image.
I use weasyprint to generate the pdf but it does not show the image.

In an html file the image does show, but in a pdf file it does not. What am I doing wrong?

view.py

def Export_pdf(request, student_id):
    student = get_object_or_404(Student, id=student_id)  
    # return render(request, 'sendInfo/home_page.html', {'student' : student})
   
    html_string = render(request, 'sendInfo/home_page.html', {'student' : student}).content
    pdf = HTML(string=html_string).write_pdf()    
    response = HttpResponse(pdf, content_type='application/pdf')
    response['Content-Disposition'] = f'attachment; filename="{student.name}.pdf"'
    return response

model.py

class Student(models.Model):      
    picture = models.ImageField(upload_to='picture/')     

home_page.html

<body>   
    <img src="{{student.picture.url}}" alt="Foto subida" width="80" height="80"/> 
  
</body>

In settings.py have the lines

STATIC_URL = 'static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static')

MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media/')

urls.py

app_name = "sendInfo"
urlpatterns = [
    path('export/<int:student_id>/', views.Export_pdf, name="export-pdf"),
]
if settings.DEBUG:
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

Are you using the django-weasyprint package, or are you using weasyprint directly?

Is this in your development environment (DEBUG=False) or your production environment (DEBUG=True)?

What versions of Django, Python, and WeasyPrint are you using?

(Should you be using render_to_string instead of render?)

KenWhitesell, thanks for answering me.

In view.py I include: from weasyprint import HTML
In settings.py I have DEBUG = True
the version of python is 3.12.3
django version 5.0.6
WeasyPrint version 63.0
I have changed render to render_to_string and the pdf does not show the image.

When the pdf is generated it does not show the photo, it shows me the alt value of the tag “Foto subida”

def Export_pdf(request, student_id):
    student = get_object_or_404(Student, id=student_id)  
    # return render(request, 'sendInfo/home_page.html', {'student' : student})
   
    html_string = render_to_string('sendInfo/home_page.html', {'student' : student})
    pdf = HTML(string=html_string).write_pdf()    
    response = HttpResponse(pdf, content_type='application/pdf')
    response['Content-Disposition'] = f'attachment; filename="{student.name}.pdf"'
    return response

I think that WeasyPrint can’t access the image using the relative URL. When you use {{student.picture.url}}, it generates a URL like /media/picture/image.jpg, but WeasyPrint needs either an absolute URL or the actual file path on the system.

Try to use absolute urls:

def Export_pdf(request, student_id):
    student = get_object_or_404(Student, id=student_id)
    
    # Build the absolute URL for the image
    base_url = request.build_absolute_uri('/')[:-1]  # Gets domain without trailing slash
    context = {
        'student': student,
        'base_url': base_url
    }
   
    html_string = render_to_string('sendInfo/home_page.html', context)
    pdf = HTML(string=html_string, base_url=request.build_absolute_uri('/')).write_pdf()
    
    response = HttpResponse(pdf, content_type='application/pdf')
    response['Content-Disposition'] = f'attachment; filename="{student.name}.pdf"'
    return response

Then in your template:

<body>   
    <img src="{{ base_url }}{{ student.picture.url }}" alt="Foto subida" width="80" height="80"/> 
</body>