Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django admin form dynamically change fields based on checkbox

I am implementing a calendar in Django and wanted to extend my functionality and add support for recurring events. My issue is I would like to have a BooleanField that toggles between single/multi-day events and recurring events. So the field would be labelled something like: Is this a recurring event? and if the user checks the box, it changes the start and end fields to display a different field.

Here is a brief version of my model.py

class Event(models.Model):

    title = models.CharField(max_length=40)

    description = models.TextField(blank=True)

    is_recurring = models.BooleanField(blank=True, default=False, verbose_name='Event is recurring?')

    start = models.DateTimeField()

    end = models.DateTimeField()    

    def __str__(self):
        return self.title

And if the user checks the is_recurring field then dynamically remove those 2 fields and change the form. Here is my admin.py:

class EventAdmin(admin.ModelAdmin):
    form = EventForm
    fieldsets = [
        (None,  {'fields': [
                                'title',
                                'description'
                            ]
                }
        ),
        (None,  {'fields':  [
                                'is_recurring',
                                'start',
                                'end',
                            ]
                }
        ),
    ]   # END fieldset

    def get_fieldsets(self, *args, **kwargs):
        return(
                (None, {
                        'fields' : ('my_extra_field',),
                    }),
            )

admin.site.register(Event , EventAdmin)

and here is my forms.py

class EventForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(EventForm, self).__init__(*args, **kwargs)
        self.fields['my_extra_field'] = forms.CharField()

    class Meta:
        model = Event

So here I was trying to add my_extra_field to the form, to try it out, but I keep getting

Unknown field(s) (my_extra_field) specified for Event. Check fields/fieldsets/exclude attributes of class EventAdmin.

and cant find a way to retrieve my field. I have an impression it might be because I'm using a fieldsets and you might want to suggest not using it, but unfortunately there is alot of info that I removed from my model to make it more appropriate for a question and therefore I need to use fieldsets.

So to finalise my question, I'm wondering how to dynamically add a field base on my check box? and as an extension to the question, how to remove 2 fields from my form?

like image 542
Philippe Fisher Avatar asked Sep 28 '22 13:09

Philippe Fisher


1 Answers

The extra field must exist on the form so you can use it in your fieldsets:

class EventForm(forms.ModelForm):
    my_extra_field = forms.CharField()   

    class Meta:
        model = Event
        exclude = tuple()  # Required in recent Django versions.
                           # Be careful not to include fields by accident.

You will probably have to override save() on your form, since ModelForm does not know what to do with your extra fields.

class EventForm(forms.ModelForm):
    my_extra_field = forms.CharField()

    def save(self, *args, **kwargs):
        if self.cleaned_data['is_recurring']:
            # do something with your extra fields,
            # remove values from other fields, etc.
        super(EventForm, self).save(*args, **kwargs)

If you want to change your form without a page reload, you need to use Javascript.

like image 146
René Fleschenberg Avatar answered Oct 03 '22 04:10

René Fleschenberg