My way or an easier way (templates)

After

I got curious if there are easier solutions to my coding mess. So 3 problems and my solutions (the mess) and I hope there are easier ways. (The first is a real problem with the checkboxes so that will probably result in a resolved)

1. Add a searchfield above a list of checkboxes
I had a few problems with the default code: ((form}}

  • I never see checkboxes
  • the search field is never shown at a convenient location in the html and associated with the correct list (can only add this is a manual template)
  • I lost my code that showed all checked list items on top of the list (css only) I will add it if I find it again)

the list of phonenumbers resulting from:

telephoneNumbers = models.ManyToManyField( to=PhoneNumber
                                    ,related_name="person"
                                   )

shows it as html not as checkboxes .

I hoped the widget CheckboxSelectMultiple would solve that

class Meta:
        model = Entity
        fields = "__all__"

        widgets = {
            'telephoneNumbers': forms.CheckboxSelectMultiple(attrs=
            {
                'type': "checkbox",
            }),
      }

But that does not change the elements into a checkbox even though the widget name implies it.

Adding the following code works

class Personform(ModelForm):
    telephoneNumbers = forms.ModelMultipleChoiceField(
            queryset = PhoneNumber.objects.all(),
            widget = forms.CheckboxSelectMultiple(attrs=
                {
                }
            ),
        )

but that means I have 'redefined' the field in the form (dont know the right word describing the problem)

So how can I create a checkbox list and how can I place the searchfield in a usefull place? Is that even possible without creating a total manual template for that?

2: All manual templates

I had to create templates for some fields and (until yesterday) that resulted in me creating a template for each field. For instance the following code for the fuull name of a person consisting of 3 form fields

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

   {% 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" %}

 </form>

with:

{% 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.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 %}

  {% 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 %}

</div>

Because I included one field this way it seams I need to add all fields this way. And because the default template code does not perform like expected (for me) that means a lot of templates to add with include.
And worse… a lot to correct if I make the same mistake in every template :frowning: And I did that to many times. I expected {{ person_form.firstName }} to create all associated fields like label, formfield errors and help_text but it only adds the form field.`

A bit clearer. I expected the result from a template like this:

{% load i18n %}

<div class="formFieldWrapper">
  <label for="{{ form.firstName.id_for_label }}">{{ form.firstName.label }}</label>

  {{ form.firstName }}

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

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

But I only get the form field:

<input type="text" name="firstName" placeholder="First name" size="30" maxlength="60" class="textinput form-control" id="id_firstName">

Crispy came to the rescue though (I found out yesterday) with
{{person_form.firstName|as_crispy_field}}

But is there a way without crispy to do this the easy way?.. add all with one commment. online people suggest {{person_form.firstName}} should do that but sadly it doesnt. Can it be easyer then the crispy solution?

3. place multiple fields in a row
I want to place the name fields in a row like
image

With

{% 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.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 %}

  {% 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 %}
</div>

it works and with crispy I might have a bit different but same solution:

<div class="row">
    {{ person_form.firstName|as_crispy_field}}
    {{ person_form.nameAffix|as_crispy_field}}
    {{ person_form.familyName|as_crispy_field}}
</div>

the solution with FormHelper did nothing. I probably did something wrong:

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.helper = FormHelper()
        self.helper.layout = Layout(
            Row(
                Column('firstName', css_class='test'),
                Column('nameAffix', css_class='test'),
                Column('familyName', css_class='test'),
                css_class='test2'
            ),
            'dateOfBirth',
            'gender',

        )

What is the best solution here?

Where is this definition? (Which model is it defined in?)

class Entity(models.Model):
    addresses = models.ManyToManyField(  to=Address
                                       , related_name="address_entities_set"
                                       , blank=True )

    websites = models.ManyToManyField(to=Website
                                      , related_name="website_entity_set"
                                      , blank=True)

    telephoneNumbers = models.ManyToManyField( to=PhoneNumber
                                    ,related_name="phonenumber_entity_set"
                                   )
    emails = models.ManyToManyField(to=Email
                                    , related_name="emails_entity_set"
                                    , blank=True)

and

class Person(Entity):
    pass

Next I use a form to show it but it shows the list like:

No checkboxes

class Meta:
     'telephoneNumbers': forms.CheckboxSelectMultiple(attrs=
            {
                'type': "checkbox",
            }),

The person_form uses

{{ person_form | crispy}} to show the fields

Using a trivial analogue (User and Group models), this works when rendering a form directly.

For example the following works in the Django shell:

from django import forms
from django.template import Template, Context

class TestForm(forms.ModelForm):
     class Meta:
         model=User
         fields=['username', 'groups']
         widgets={'groups': forms.CheckboxSelectMultiple(attrs={})}

form = TestForm()

template = Template('{{form}}')
context = Context({'form': form})

print(template.render(context))

yields:

<div>
    <label for="id_username">Username:</label>

<div class="helptext" id="id_username_helptext">Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.</div>

<input type="text" name="username" maxlength="150" required aria-describedby="id_username_helptext" id="id_username">
    
</div>

  <div>
    <fieldset aria-describedby="id_groups_helptext">
  <legend>Groups:</legend>

<div class="helptext" id="id_groups_helptext">The groups this user belongs to. A user will get all permissions granted to each of their groups.</div>

<div id="id_groups"><div>
    <label for="id_groups_0"><input type="checkbox" name="groups" value="1" id="id_groups_0">
 Group 1</label>

</div><div>
    <label for="id_groups_1"><input type="checkbox" name="groups" value="2" id="id_groups_1">
 Group 2</label>

</div><div>
    <label for="id_groups_2"><input type="checkbox" name="groups" value="3" id="id_groups_2">
 Group 3</label>

</div><div>
    <label for="id_groups_3"><input type="checkbox" name="groups" value="4" id="id_groups_3">
 Group 4</label>

</div>
</div></fieldset>
</div>

So, this implies to me that there’s something else involved here. Could be an overridden template, could be some other third-party library involved, could be any number of things.

The Django Debug Toolbar can be helpful with situations like this, especially if you set the SKIP_TEMPLATE_PREFIXES to display all the templates being rendered. (It will generate a lot of output, but sometimes that’s necessary.)

Thank you. I will use that to see if I can find the solution