# Rendering PDF from django templates

Again, more of a note to self than a real tutorial. I'll try not to make it obtuse. 

Your pod/container must have a compatible [*wkhtmltopdf*](https://wkhtmltopdf.org/) installed (yes, I'm weaned off of docker. It's podman all the way baby!). 
This is very important and something that has tripped me up more than once. 

Other than that just follow the installation and setup tutorials of [django](https://www.djangoproject.com/), [django rest framework](https://www.django-rest-framework.org/) and [django-dbtemplates](https://django-dbtemplates.readthedocs.io/en/latest/) to get the settings and urls in order. 

 > Key points 
  - Templates can be files on disk or stored in database
  - If the template renders on the server, it will render as PDF
  - PDF renders extremely true to the template

The files

> requirements.txt

```text
django
djangorestframework
pdfkit
# django-dbtemplates
# pip package lags behind
git+https://github.com/jazzband/django-dbtemplates.git#egg=django-dbtemplates
``` 

> serializers.py

```python

from dbtemplates.models import Template
from rest_framework import serializers

class PDFCreatorSerializer(serializers.Serializer):                                                                                                                 
    id = serializers.IntegerField(read_only=True)                                                                                          
    template = serializers.CharField(max_length=256)                                                                                                 
    template_data = serializers.JSONField()                                                                                                          
    filestore_data = serializers.JSONField() 

class FileStoreResponseSerializer:  # Topic for another blog post
    ...

class TemplateSerializer(serializers.ModelSerializer):
    class Meta:
        model = Template
        fields: str = "__all__"
 
``` 

> views.py

```python
from io import BytesIO
import uuid
import json
from typing import Tuple
from django.conf import settings
from django.http import HttpRequest
from dbtemplate.models import Template
from rest_framework import viewsets, permissions
from rest_framework.response import Response
from . import serializers

class RenderPDFTemplate(viewsets.ViewSet):
     serializer_class = serializers.PDFCreatorSerializer
    def create(self, request: HttpRequest) - > Response:
        pdf, filename = self.create_pdf_from_template(
            request.POST.get("template_data", ""),
            request.POST.get("template", "")
       )
       .
       .
       . do file store stuff..
       return Response(...)

    def create_pdf_from_template(self, data: str, template_name: str) -> Tuple[BytesIO, str]:
        data = json.loads(data)
        data.update({"base": settings.BASE_DIR.parent.parent})
        template = get_template(template_name=template_name)
        outfile = uuid.uuid1().hex + ".pdf"
        html = template.render(data)
        options = {
            "page-size": "A4",
            "margin-top": "0.55in",
            "margin-right": "0.25in",
            "margin-bottom": "0.25in",
            "margin-left": "0.25in",
            "encoding": "UTF-8",
            "quiet": "",
            "enable-forms": None,
           "enable-local-file-access": "",
        }
        pdf = pdfkit.from_string(html, False, options)
        return (pdf, outfile)

class BaseModelViewSetWithPermissions(viewsets.ModelViewSet):
    """CRUD"""
    permission_classes = (permissions.IsAuthenticated | permissions.IsAdminUser,)                                                                                                                   

class TemplateViewSet(BaseModelViewSetWithPermissions):
    queryset = Template.objects.all()
    serializer_class = serializers.TemplateSerializer
```

To test it, create a client

```python
import requests
import json

URL = "https://yourdjangoserver/renderpdf/"
TOKEN = "The DjangoRestFrameworkToken you created in admin"
HEADERS = {"Authorization": f"{TOKEN}"}

DATA = {
    "template_name": "yourtemplate.html" , 
    "template_data": json.dumps({"somehing": "else", "more": "of the same", "date": "2022-02-02"}, default=str),
} 
res = requests.post(URL, headers=HEADERS, data=DATA, verify=False)

``` 

Simple as that!
