Opened 3 years ago

Closed 3 years ago

Last modified 3 years ago

#32364 closed Uncategorized (worksforme)

ModelAdmin.formfield_overrides drops TEMPLATES...DIRS while loading a custom widget template within a std admin form template

Reported by: zoltan-ky Owned by: nobody
Component: Template system Version: 3.1
Severity: Normal Keywords: formfield_overrides
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: yes
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

Using Django 3.1.5. This custom widget "idea" is a minimal demo-version based on https://docs.djangoproject.com/en/3.1/ref/contrib/admin/#django.contrib.admin.ModelAdmin.formfield_overrides.

So I'd like to use a MyTextArea widget with its mytextarea.html on models.TextField (myapp.Post.body) below and use it to edit Posts within the admin. (I know how to do it through forms, creating my form fields *and* my widgets, but that's a workaround).

When I 'runserver' and try to add a new Post under the admin a "django.template.exceptions.TemplateDoesNotExist: myapp/mytextarea.html" exception is thrown.

What am I missing in the test setup below?

I have traced the problem, as it is set up, (using pdb) to the EngineMixin class (django/forms/renderer.py:39) which has a 'hard-coded' backend ' named 'djangoforms'. This DjangoTemplates instance used to instantiate MyTextArea is different from the one used to find the admin form template. Somewhere, and I don't understand enough of what's going on here, the 'dirs' property of the first Engine (used for the form template) gets dropped and not passed to the Engine used to load the custom widget template.

To recreate (django 3.1.5): starting with a new: django-admin startproject myproject; ... startapp myapp. After creating the few small files below, migrate, createsuperuser for admin.

In the startproject-created *myproject/myproject/settings.py* the only changes are:

  • 'myapp' is added to INSTALLED_APPS
  • TEMPLATES...DIRS: [ BASE_DIR / 'templates' ],

to use project-wide templates.

The files:
myapp/admin.py:

from django.contrib import admin
from django.db import models
from myapp.models import Post
from myapp.widgets import MyTextWidget
# Register your models here.
class PostAdmin(admin.ModelAdmin):
    formfield_overrides = {
        models.TextField: {'widget': MyTextWidget}
    }
admin.site.register(Post, PostAdmin)

myapp/models.py:

from django.db import models
# Create your models here.
class Post(models.Model):
    body = models.TextField()

myapp/widgets.py:

from django import forms
from django.contrib.admin import widgets
class MyTextWidget(forms.Textarea):
    template_name = 'myapp/mytextarea.html'

<project>/templates/myapp/mytextarea.html:

{# based on django/forms/templates/django/forms/widgets/textarea.html #}
<textarea name="{{ widget.name }}"{% include "django/forms/widgets/attrs.html" %}>
<p>MY TEXTAREA</p>
{% if widget.value %}{{ widget.value }}{% endif %}</textarea>

Change History (2)

comment:1 by Mariusz Felisiak, 3 years ago

Resolution: invalid
Status: newclosed

See docs about Overriding built-in widget templates. You should use FORM_RENDERER = 'django.forms.renderers.TemplatesSetting'.

Please don't use Trac as a support channel. Closing per TicketClosingReasons/UseSupportChannels.

comment:2 by zoltan-ky, 3 years ago

Needs documentation: set
Resolution: invalidworksforme

My apologies. I should have posted on the support channel first and will do so in the future.

There is no mention of this need at https://docs.djangoproject.com/en/3.1/ref/contrib/admin/#django.contrib.admin.ModelAdmin.formfield_overrides and is the example I followed

Maybe that part of the admin documentation should be updated to avoid the trap.

Note: See TracTickets for help on using tickets.
Back to Top