Can't override default widget on ModelForm

Hi,

I’d like to replace the default dropdown widget that appears on the following form by radio buttons. I wrote the following code but dropdowns are still present.

models.py:

from django.db import models
from django import forms
from django.utils.translation import gettext_lazy as _
import datetime 

ANNEE_NAISSANCE = []
for r in range(1920, (datetime.datetime.now().year+1)):
    ANNEE_NAISSANCE.append((r,r))

class Questionnaire(models.Model):
    
    class Genre(models.TextChoices): 
        FEMININ = 'Féminin', _('Féminin')
        MASCULIN = 'Masculin', _('Masculin')
        NON_BINAIRE = 'Non binaire', _('Non binaire')
        PAS_DE_REPONSE = 'Ne souhaite pas préciser', _('Je ne souhaite pas le préciser')
        AUTRE = 'Autre', _('Autre (préciser)')
    genre = models.CharField(
        _('Quel est votre genre ?'),
        max_length=24,
        choices=Genre.choices,
    )
    naissance = models.IntegerField(
        _('quelle est votre année de naissance ?'), 
        choices=ANNEE_NAISSANCE, 
    )
    class Diplome(models.TextChoices):
        SANS_DIPLOME = 'Sans diplôme', _('Sans diplôme')
        BEPC = 'BEPC, brevet élémentaire, brevet des collèges, DNB', _('BEPC, brevet élémentaire, brevet des collèges, DNB')
        BEP_CAP = 'BEP/CAP', _('BEP/CAP')
        BACCALAUREAT = 'Baccalauréat', _('Baccalauréat')
        DEUG = 'DEUG, BTS, DUT, DEUST', _('DEUG, BTS, DUT, DEUST')
        LICENCE = 'Licence, licence professionnelle', _('Licence, licence professionnelle')
        MAITRISE = "Maîtrise, Master, diplôme d'études approfondies, diplôme d'études supérieures spécialisées, diplôme d'ingénieur", _("Maîtrise, Master, diplôme d'études approfondies, diplôme d'études supérieures spécialisées, diplôme d'ingénieur")
        DOCTORAT = 'Doctorat', _('Doctorat')
    diplome = models.CharField(
        _('quel est le diplôme le plus élevé que vous ayez obtenu ?'),
        max_length=230,
        choices=Diplome.choices,
    )

forms.py (where is my attempt at defining the custom widget):

from django import forms
from django.db import models
from .models import Questionnaire, ANNEE_NAISSANCE

class QuestionnaireForm1(forms.ModelForm):
  class Meta:
    model = Questionnaire
    fields = ['genre', 'naissance', 'diplome']
    widgets = {
      'genre': forms.RadioSelect,
    }

questionnaire_form.html:

{% extends 'form1/base.html' %}

{% block content %}

  <form action="" method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <input type="submit" value="Submit">
  </form>

{% endblock %}

Am I missing something?

Thanks!

What does your view look like for this? (Is it possible you’re not rendering the form you think you’re rendering?)

Hi Ken,

Sorry, I forgot about views.py. Here it is:

from django.views.generic.edit import CreateView
from form1.models import Questionnaire
from django.urls import reverse_lazy

class CreerSoumission(CreateView):
    model = Questionnaire
    fields = ['genre', 'naissance', 'diplome']

It’s still a work in progress of course.

I don’t see where you’re specifying that you want to use QuestionnaireForm1 in that view. It looks like the view is going to use a default form for that model.

1 Like

Right, thanks for the hint!

I tried

from django.views.generic.edit import CreateView
from form1.models import Questionnaire
from form1.forms import QuestionnaireForm1
from django.urls import reverse_lazy

class CreerSoumission(CreateView):
    model = Questionnaire
    fields = ['genre', 'naissance', 'diplome']
    form = QuestionnaireForm1

but I get the following error:

'ModelFormOptions' object has no attribute 'private_fields'

Could you point me to the appropriate syntax?

I believe the attribute is form_class, not form.

It is indeed! And specifying both ‘fields’ and ‘form_class’ is not permitted, so:

from django.views.generic.edit import CreateView
from form1.models import Questionnaire
from form1.forms import QuestionnaireForm1

class CreerSoumission(CreateView):
    model = Questionnaire
    form_class = QuestionnaireForm1

This works.
Thanks a lot!