2

I am trying replace widget template with my own, but I am getting a TemplateDoesNotExist error.

In app\forms.py:

class SelectPlus(Select):
    template_name = 'selectplus.html'


class SimpleForm(ModelForm):
    somefield = ModelChoiceField(
        queryset=SomeObjects.objects.all(), 
        widget=SelectPlus(attrs={'url': 'custom_url_to_context'})
    )

In settings.py

TEMPLATES = [
{
    'BACKEND': 'django.template.backends.django.DjangoTemplates',
    'DIRS': [ROOT_PATH, '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',
        ],

    },
},

In debug trace I see that template-loader doesn't search in apps folders or main template folder:

enter image description here

But all other templates works fine.

Alasdair
  • 298,606
  • 55
  • 578
  • 516
Nikita Bel
  • 189
  • 1
  • 12

2 Answers2

1

In Django 1.11:

# app/widgets.py
from django.forms.widgets import DefaultWidget

class SelectPlus(DefaultWidget):
    template_name = 'app/selectplus.html'

Import the widget that you want to modify. Your choices can be found here: https://docs.djangoproject.com/en/1.11/ref/forms/widgets/#built-in-widgets

Create a subclass and specify the template name.

# app/templates/app/selectplus.html
<select name="{{ widget.name }}"{% include "django/forms/widgets/attrs.html" %}>{% for group_name, group_choices, group_index in widget.optgroups %}{% if group_name %}
  <optgroup label="{{ group_name }}">{% endif %}{% for option in group_choices %}
  {% include option.template_name with widget=option %}{% endfor %}{% if group_name %}
  </optgroup>{% endif %}{% endfor %}
</select>

Create your template. This is copied exactly from django/forms/widgets/select.html but you can put anything you want here. You can also reference other existing widget templates for inspiration. Your choice can be found here: https://github.com/django/django/tree/master/django/forms/templates/django/forms/widgets

# app/forms.py
from .widgets import SelectPlus

class SimpleForm(ModelForm):
    my_field = forms.ExampleField(widget=SelectPlus())

Import your customer widget (SelectPlus) and add it to a field in your form.

Finally, in your template, render the main field and it will reference app/templates/app/selectplus.html.

brunosardinepi
  • 125
  • 1
  • 7
0

You have two ways to fix this.

1) fixing your templates path, like this.

TEMPLATES = [
{
    'BACKEND': 'django.template.backends.django.DjangoTemplates',
    'DIRS': [ROOT_PATH, os.path.join(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',
        ],

    },
}

2) Add template folder inside the app.

Diego Puente
  • 1,964
  • 20
  • 23