Form.template_name Issue: TemplateNotFound

I wanted to try the new Form.template_name feature of Django 4.0 following this approach, but I am getting a TemplateDoesNotExist error.

# forms.py
class MyForm(forms.Form):
    title = forms.CharField()
    template_name = "common/custom_form.html"
# In your template:
{{ form }}

# In templates/common/custom_form.html:
{% for field in form %}
    <div class="fieldWrapper">
        {{ field.errors }}
        {{ field.label_tag }} {{ field }}
    </div>
{% endfor %}

It seems the renderer is not looking in the right directory. The debugger shows this:

Using engine django:

    django.template.loaders.filesystem.Loader: /root/.cache/pypoetry/virtualenvs/project/lib/python3.9/site-packages/django/forms/templates/common/custom_form.html (Source does not exist)
    django.template.loaders.app_directories.Loader: /root/.cache/pypoetry/virtualenvs/project/lib/python3.9/site-packages/django/contrib/admin/templates/common/custom_form.html (Source does not exist)
    django.template.loaders.app_directories.Loader: /root/.cache/pypoetry/virtualenvs/project/lib/python3.9/site-packages/django/contrib/auth/templates/common/custom_form.html (Source does not exist)
    django.template.loaders.app_directories.Loader: /root/.cache/pypoetry/virtualenvs/project/lib/python3.9/site-packages/allauth/templates/common/custom_form.html (Source does not exist)
    django.template.loaders.app_directories.Loader: /root/.cache/pypoetry/virtualenvs/project/lib/python3.9/site-packages/ordered_model/templates/common/custom_form.html (Source does not exist)

Other templates used for views are loaded successfully from the the configured template directory.

# settings.py
TEMPLATES = [
    {
        "BACKEND": "django.template.backends.django.DjangoTemplates",
        "DIRS": [BASE_DIR / "templates"],
        "APP_DIRS": True,
        "OPTIONS": {
            "context_processors": [
                "django.template.context_processors.debug",
                "django.template.context_processors.request",
                "django.contrib.auth.context_processors.auth",
                "django.contrib.messages.context_processors.messages",
            ],
        },
    },
]

I’m using Django 4.0.1 running on Docker.

Am I missing anything? Is there any additional configuration needed for the form renderer? Many thanks!

1 Like

Something seems odd in that error message - it says it’s looking for “custom_form.html”, but the snippet is defined for “form_snippet.html”. Can you confirm that everything else on this view is working correctly by commenting out the template_name attribute on your MyForm class?

1 Like

Sorry, my bad. I’ve changed the filename to simplify the snippets, but didn’t update the error message… Changed it back to the filename I’m actually using. Hope it makes more sense now. Other that that everything else in the view is working, e.g. if I replace {{form}} with {{form.as_p}} or render the form fields individually within the view template.

You show your form as being in:

Is that in your BASE_DIR/templates directory or somewhere else?

yes exactly, there is a folder templates in the root directory of the project, where all templates are stored.

Try placing that form template in your app/templates/common directory, where app is the app containing that form.

3 Likes

Mmm, interesting. If I put it into the templates folder with the app, i.e. my_app/templates/my_app/custom_form.html, it works. In a templates directory in the project root it doesn’t. Not quite sure why. But thanks for the suggestion.

I’m facing the same issue: if the form template goes into my templates/app_name/ directory, together will all my other templates, Django can’t find it.

But if I place it inside the app_name/templates/app_name/ it works.

Just bumping this because I had the same exact issue. When my form template is in the main templates/app_name directory, Django can’t find it, but in app_name/templates/app_name/ there seems to be no problem.

+1 I am experiencing the same issue with using a form class

class ProfileChangeForm(UserChangeForm):
    template_name = "accounts/profile_change_form.html"

    class Meta:
        model = get_user_model()
        fields = (
        # snip
        )

First, this topic has been marked as solved. You’re likely going to get more attention to your post if you open up a new topic.

Second, did you read through the full thread here? Do you have your template in the proper directory as described above? If you have - or think you have - and it’s still not working, please include a description of your directory structure for your app and templates.

Yes, using the app_name/templates/app_name/* folder is a work around the issue. However, I don’t think that this resolved the root of the problem that the template_name cannot resolve a template in a directory that was marked as a template folder.

TEMPLATES = [
    {
        # ... snip
        "DIRS": [BASE_DIR / "templates"],
        "APP_DIRS": True,
        "OPTIONS": {
            "context_processors": [
                "django.template.context_processors.debug",
                "django.template.context_processors.request",
                "django.contrib.auth.context_processors.auth",
                "django.contrib.messages.context_processors.messages",
            ],
        },
    },
]

maybe a better place for this is in the github repo.

by the way, thank you very much for the reply

My understanding is that there are ways to customize the rendering engine to add the directories when searching for form templates. I’ve never needed to do this, so I’m not really familiar with the details.

See (among others):

2 Likes

After explicitly registering django.forms in INSTALLED_APPS
and defining FORM_RENDERER = 'django.forms.renderers.TemplatesSetting',
Django was able to find my custom template in the templates folder in the root directory of my project. :blush:

1 Like

Just encountered this as well, such a weird edge-case haha, I do see this is kinda documented at least. But this worked great, thanks!