In the case where you need to use custom template tags, @Gourneau's answer did not work for me. I had to configure settings (in my main.py) like this:
import django
from django.conf import settings
from django.template.loader import get_template
settings.configure(
    TEMPLATES=[
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': ['templates'],
        'APP_DIRS': False,
        'OPTIONS': {
            'libraries': {
                'custom_filters': 'templatetags.custom_filters',
            },
        },
    },
])
django.setup()
where my folder structure looks like this:
- main.py
- templates/
  - test_results.html
- templatetags/
  - __init__.py
  - custom_filters.py
and custom_filters.py looks like this:
from django import template
import pandas as pd
import base64
from django.utils.safestring import mark_safe
register = template.Library()
@register.filter
def nl_to_br(string:str):
    return mark_safe( string.replace("\n", "<br>") )
Now I could simply use (in main.py):
template = get_template('test_results.html')
context = {
    "results": results
}
test_results = template.render(context)