How to change a form name in class based view?

In a function based view I can change the form name for use in templates like:

Note: lot of code left out because it is not usefull for this example.

def create_person(request):
    person_form = PersonModelForm(data = request.POST)
    phonenumber_form = PhoneNumberForm(data = request.POST)

   context = {'person_form': person_form,
               'phonenumber_form': phonenumber_form }

    return render(request,
                  template_name="MyNetwork\\person_form_test.html",
                  context=context) 

Since I manully create a lot of templates for fields and try to re-use templates I would like to know how to change the name of the form (used in template) in a class based view.

Thanks

Are you looking to change the name of the form as it is used in the templates, or change the form class being used? (Two different answers.)

If you’re looking to share/reuse templates for similar-but-not-identical situations, you’re probably best off using generic names for the form(s) in the template.

Example:
In view #1:

context = {'form_1': person_form, 'form_2': phonenumber_form}

In view #2:

context = {'form_1': person_form, 'form_2': address_form}

Both of these contexts can be rendered by the same template as:

{{ form_1 }}
{{ form_2 }}

If you’re looking to change the form being used by a CBV, you use the form_class attribute. (See the second example at Basic forms)

I am looking at changing the the first… and atm specifically for forms.

I can do that in the function based views as seen in the code but I cannot find how to in the class based views.

I want to use the same templates in both function based views and class based views for forms. the above code is the solution for function based views but if I use

{{ form_1 }}

I want to rename the form in class based views to form_1 too

Is there a way to change the name in the

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['title'] = _('title')
        return context

function in the CBV?

Can I use

in CBV too?

What are your actual objectives here? What are the benefits that you are hoping to obtain?

It might be helpful if you posted the CBV that you’re trying to alter the behavior of, and identify specifically what your end goal is.

I know you’re trying to address this in general terms, but there’s still a lot of ambiguity regarding the desired results.

In general terms, you’re frequently better off adapting your templates to work with the CBVs rather than the reverse, but it’s not a requirement.

Specifically, regarding this:

What “name” are you referring to?

If you’re not familiar with the Django CBV internals, I recommend becoming familiar with the Classy Class-Based Views site, specifically, the FormView to get an understanding of what attributes, variables, and functions are used by that view.

half sentence from me :frowning:
The name of the form, as used in the templates, provided by a class based view like a UpdateView

So you’ve got a couple different angles to this.

  1. By default, an UpdateView expects the instance of the form to be rendered to be present in the context by the name “form”. That’s the easiest way to handle this. Have your template render {{ form }}, and the rest works directly.
    -or-
  2. Override the get_context_data function to assign the form instance to the name being used in the template.
    e.g.:
def get_context_data(self, **kwargs):
    context = super().get_context_data(**kwargs)
    context["my_form"] = get_form()
    return context

(There may be more to this, but this is the basic idea.)

My recommendation is always try to work with the framework, and so I would generally recommend option #1.

Reply to previous post (3 above I think)

My objective is to re-use as mutch code as possible.
I will try to show the process that resulted in me wanting to change the form name in class based views:

  • I had problems showing some fields so I changed all my forms to manually created parts per model field. For instance my person form template consists of:
{% extends 'main-template.html' %}
{% load i18n %}
{% block content%}

<div class="center-form">
  <form method="post" class="edit">
    {% csrf_token %}

    <fieldset>
      <legend>{% translate "person" %}</legend>
      {% include "MyNetwork/form/person/full_name_fields_form.html" %}
      {% include "MyNetwork/form/person/gender_field_form.html" %}
      {% include "MyNetwork/form/person/date_of_birth_field_form.html" %}

      {% include "MyContext/form/context/subjects_field_form.html" %}
    </fieldset>    
  </form>
</div>

{% endblock content %}

And to show the full name fields I created the template refered to above that shows all name fields beside eachother like:
image

and the code:

{% load i18n %}

<div class="form-element-group">
  <label for="{{ form.familyName.id_for_label }}">{% translate "full name"%}</label>
  <span>
  {{ form.firstName }}
  {{ form.nameAffix }}
  {{ form.familyName }}
  </span>

  {% if form.firstName.errors or form.nameAffix.errors or form.familyName.errors %}
  <div class="errors">
    {{ form.firstName.errors }}
    {{ form.nameAffix.errors }}
    {{ form.familyName.errors }}    
  </div>
  {% endif %}

  {% if form.firstName.help_text or form.nameAffix.help_text or form.familyName.help_text %}
  <div class="help">
     {{ form.firstName.help_text }} 
     {{ form.nameAffix.help_text }}
     {{ form.familyName.help_text }}
  </div>
  {% endif %}
</div>

All templates use form.fieldname

  • But some time ago I wanted to add all fields for phonenumbers to the person form (see a terrible post before):
class PhoneNumber(models.model):
    '''The phonenumbers related to entities'''
    telephoneNumber  = models.CharField(_('telephonenumber'), max_length=22)

So I created a function based view with

        person_form = PersonModelForm(data = request.POST)
        phonenumber_form_set = PhoneNumberFormSet(data = request.POST)

But now my templates get two forms with different names.

     {{ form.firstName}}

no longer works. It has to be

   {{person_form.firstName}}

But in my class based views I still get the form instead of person_form

So I see 2 options:

  1. Double my code… some with person_form.fieldname and others with form.fieldname
  2. change the default form name for my templates in my other class based views so I can use person_form in my PersonUpdateView etc..

So that is why I want to change the name form to person_form in my person related class based forms. Is that possible or is there a third solution?

I agree but see my bigger post to see why I think option two is my current solution… And thanks again for all reply’s

If the section of the template that includes these lines:

Is what’s in one of the include directives, perhaps:

Then keep in mind that you can assign a name to a context reference in the include statement with the with directive. See include.

This means you can do something like:
{% include "MyNetwork/form/person/full_name_fields_form.html" with form=form_1 %}
and
{% include "MyNetwork/form/person/full_name_fields_form.html" with form=form_2 %}

where references to form within the full_name_fields_form.html template are referring to the context entries form_1 and form_2 respectively.

The templating system is very much designed around being flexible and used in a “generic” manner. Look at the system provided templates for things like the admin and the standard widgets to get some ideas as to just how flexible they can be.

And so the reason I recommend going with option 1 above is that learning how to create and use these types of generic templates goes a long way toward reducing duplicated functionality.

Now, having said all this, I will point out that the Django-provided CBVs are not a good solution for “multiple-form” views. Yes, they can be adapted to handling multiple forms, but it’s not really what they’re designed to do and you end up having to override more functionality than you might like to ensure that both forms are handled properly.

If you have multiple views where each view is having to properly manage multiple forms, my suggestion is to either use FBVs - or if you have enough of these where it’s worthwhile to do so, create your own CBVs starting from View.

I dont see how I can do that but I will start a few topics soon to see if / how/if there are better solutions for my problems. I have a fewproblems I solved by creating manual templates and a lot of extra code. I will see if that can be done easyer. That said… you gave me the solution I asked for and a lot to think about. thanks for all the help.