Search code examples
djangodjango-formsdjango-generic-views

How does one use a custom widget with a generic UpdateView without having to redefine the entire form?


I have a model with a ManyToMany relation that I would like to update with a CheckBoxSelectMultiple widget while everything else uses the default generic form, but when I redefine that one form field, it is the only one that shows up in the UpdateView. Is there a way to use a widget with just one field without having to redefine the entire form?

Views.py:

from django.views.generic.edit import UpdateView

from kunden.models import Kunde, Unternehmenstyp
from kunden.forms import KundeEditForm

class KundeUpdate(UpdateView):
    model = Kunde
    form_class =  KundeEditForm
    template_name = 'kunden/kunde_update.html'
    success_url = '/'

forms.py:

from django.forms.widgets import CheckboxSelectMultiple
from django.forms import ModelMultipleChoiceField,ModelForm

from kunden.models import Kunde, Unternehmenstyp

class KundeEditForm(ModelForm):
    model = Kunde
    unternehmenstyp = ModelMultipleChoiceField(widget=CheckboxSelectMultiple,required=True, queryset=Unternehmenstyp.objects.all())

I know this has a painfully simple solution, so thanks for your patience in advance everyone.

While I'm at it can anyone recommend any django books worth reading? I've gone through the base tutorial, dug through documentation as needed, and read Two Scoops of Django: https://django.2scoops.org/ so if you can think of a book for someone at my level, that'd be greatly appreciated. thanks again


Solution

  • Try this, with class Meta:

    from django.forms.widgets import CheckboxSelectMultiple
    from django.forms import ModelMultipleChoiceField,ModelForm
    
    from kunden.models import Kunde, Unternehmenstyp
    
    class KundeEditForm(ModelForm):
        class Meta: # model must be in the Meta class
            model = Kunde
        unternehmenstyp = ModelMultipleChoiceField(widget=CheckboxSelectMultiple,required=True, queryset=Unternehmenstyp.objects.all())
    

    REF: https://docs.djangoproject.com/en/1.5/topics/forms/modelforms/#modelform

    You can also use modelform factories if you only need to make a simple override:

    from django.views.generic.edit import UpdateView
    from django.forms.models import modelform_factory
    
    from kunden.models import Kunde, Unternehmenstyp
    
    class KundeUpdate(UpdateView):
        model = Kunde
        form_class =  modelform_factory(Kunde,
            widgets={"unternehmenstyp": CheckboxSelectMultiple })
        template_name = 'kunden/kunde_update.html'
        success_url = '/'
    

    REF: https://docs.djangoproject.com/en/1.5/topics/forms/modelforms/#modelform-factory-function