HBMCS
HBMCS

Reputation: 776

Dynamic required fields according to user's selection in Django form

I would like to make two fields (repertoire and performer) required only if the user selects and submits a type="performance". This is my model:

class Event(models.Model):

    EV_TYPE = (
        ('performance', 'performance'),
        ('other', 'other'),
    )

    title = models.CharField(max_length=200)
    type = models.CharField(max_length=15, choices=EV_TYPE, default="performance")
    repertoire = models.ManyToManyField(Work, blank=True)
    performer = models.ManyToManyField(Profile, limit_choices_to={'role__type__contains': 'Performer'})

My form:

class EventForm(forms.ModelForm):

    class Meta:
        model = Event
        fields = [
            'type',
            'submitted_by',
            'title',
            'repertoire',
        ]

My view:

def event_create_view(request):

if request.method == 'POST':
    form_event = EventForm(
        request.POST,
        repertoire_required=(not (active_user.id == 17)), # if the user is NMS then the repertoire field is not compulsory
        initial={'submitted_by' : active_user.profile.id}
        )
    form_venue = AddVenueForm()
    form_profile = ProfileForm()
    form_work = WorkFromEventForm()

    if form_event.is_valid():

        this_event = form_event.save()
        return redirect('event-edit', id=this_event.id)

This is what I tried. In the above 'form_event.is_valid', I did:

    if form_event.is_valid():


        this_event = form_event.save(commit=False)
        if this_event['type'] == 'performance' and this_event['performer'] and this_event['repertoire']:
            this_event.save()
            return redirect('event-edit', id=this_event.id)

This doesn't work though (I still get a 'this field is required' when I submit). How can I achieve what I want to do?

Addendum

This is also not working:

if 

this_event['type'] == 'performance' and not this_event['performer'] or not this_event['repertoire']:
                messages.error(request, form_event.errors)
            else:
                this_event.save()
                

Upvotes: 2

Views: 1501

Answers (1)

markwalker_
markwalker_

Reputation: 12849

You do that with a clean method on the form.

For example you might do;

def clean(self):
    """
    Validate the form input
    """
    cleaned_data = super().clean()
    type = cleaned_data.get('type')

    if type == 'performance':
        repertoire = cleaned_data.get('repertoire')
        performer = cleaned_data.get('performer')
        if not repertoire:
            self.add_error('repertoire', _("This field is required"))
        if not performer:
            self.add_error('performer', _("This field is required"))

    return cleaned_data

The docs for form validation are here; https://docs.djangoproject.com/en/3.1/ref/forms/validation/

Upvotes: 2

Related Questions