Rendering form elements not appearing

Hi all.

I have a contact form and when I use the {{ form }} the elements render as expected. However, when attempting to render individual elements of the form, nothing appears on the screen. I have included django.forms in INSTALLED_APPS and have defined FORM_RENDERER = ‘django.forms.renderers.TemplatesSetting’.

INSTALLED_APPS = [
    "polls.apps.PollsConfig",
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'django.forms',
]

Later in settings.py I include the following:

FORM_RENDERER = 'django.forms.renderers.TemplatesSetting'

forms.py is defined as follows:

from django import forms
from django.core.validators import RegexValidator
from django.forms import MultiValueField, CharField

class PhoneField(MultiValueField):
    def __init__(self, **kwargs):
        # Define one message for all fields.
        error_messages = {
            "incomplete": "Enter a country calling code and a phone number.",
        }
        # Or define a different message for each field.
        fields = (
            CharField(
                error_messages={"incomplete": "Enter a country calling code."},
                validators=[
                    RegexValidator(r"^[0-9]+$", "Enter a valid country calling code."),
                ],
            ),
            CharField(
                error_messages={"incomplete": "Enter a phone number."},
                validators=[RegexValidator(r"^[0-9]+$", "Enter a valid phone number.")],
            ),
            CharField(
                validators=[RegexValidator(r"^[0-9]+$", "Enter a valid extension.")],
                required=False,
            ),
        )
        super().__init__(
            error_messages=error_messages,
            fields=fields,
            require_all_fields=False,
            **kwargs
        )


class ContactForm(forms.Form):
    #subject = forms.CharField(max_length=100)
    message = forms.CharField(widget=forms.Textarea)
    sender = forms.EmailField(label="email")
    cc_myself = forms.BooleanField(required=False)
    phone = PhoneField(label="phone")

    first_name = forms.CharField(label="first_name", max_length=100)
    last_name = forms.CharField(label="last_name", max_length=100)

Since the form is on the index page, my view is:

def index(request):
    context = {}
    form = ContactForm()
    rendered_form = form.render("contact_form.html")
    context = {"form": rendered_form}

    return render(request, "index.html", context)

And here is my contact_form.html

{% load static %}

<form name="contact-form" class="white-text contact-form" action="/submit-form" method="POST">
    <div class="white-text">blah</div>
    {% csrf_token %}

    {{form}}

    <input type="submit" value="Submit">
</form>

In my index.html I include it as follows:

{% include "contact_form.html" %}

In the contact_form.html template, when I attempt to reference a single field, e.g. {{form.first_name}}, nothing appears. However {{form}} will include the entire form with all fields.

Can anyone point tell me what I’m doing wrong? Additionally, I notice that when the form does render with {{form}}, it seems to include the template portion of the form element twice. The

that says “blah” appears twice as does the “submit” button. The form fields each appear only once except for the submit button which is there twice. I assume it has something to do with my “include”.

Any help appreciated.

Thanks in advance.

Welcome @marcusdiaz !

The basic problem here is that you are not passing the form through to the template, you’re passing text.

You are rendering the form at:

which is going to produce HTML text, not a form object.

That means your context is not passing a “form” object through to your render function at:

And so inside the index.html template, the form in the context is text - not a form from which you can reference individual fields.

For a better understanding of what’s going on here, examine the output and datatype of rendered_form.

Thanks this helped. I updated my view as follows and now I can reference e.g. {{form.first_name}}.

def index(request):
    context = {}
    form = ContactForm()
    context = {'form': form}

    return render(request, "index.html", context)