Home > other >  How can I access the instance of the object on a django form?
How can I access the instance of the object on a django form?

Time:09-09

I have a Django related question for which I can't seem to find a proper answer:

Given this form that gets it's field data from a queryset to another model:

class EditTripForm(ModelForm):
    start_date = forms.DateField(label='Desde', widget=MyDateInput(attrs={'class': 'form-control'}))
    end_date = forms.DateField(label='Hasta', widget=MyDateInput(attrs={'class': 'form-control'}))
    operations = forms.ModelMultipleChoiceField(
        widget = forms.CheckboxSelectMultiple,
        queryset = OperationCard.objects.order_by('-date').all()
    )

    class Meta:
        model = Trip
        fields = ['start_date', 'end_date', 'operations']

I would like to filter the queryset so that I can use the form's own start_date or end_date to make a query like this:

class EditTripForm(ModelForm):
    start_date = forms.DateField(label='Desde', widget=MyDateInput(attrs={'class': 'form-control'}))
    end_date = forms.DateField(label='Hasta', widget=MyDateInput(attrs={'class': 'form-control'}))
    operations = forms.ModelMultipleChoiceField(
        widget = forms.CheckboxSelectMultiple,
        queryset = OperationCard.objects.order_by('-date').filter(date__gte=start_date)
    )

    class Meta:
        model = Trip
        fields = ['start_date', 'end_date', 'operations']

Note the .filter(date_gte=start_date) part

Is that even possible? How should I approach this?

CodePudding user response:

It's not possible with django by default. The user won't fill in the end_date field until after the form has been generated by django and sent to the browser, so django won't know what the value of end_date is when it creates the possible values for operations.

Generally speaking, you would need to use javascript to manipulate the possible values of a field within the page itself, or split the form into two so that you can submit the values from the first form and use them to create the possible values of the second.

CodePudding user response:

Depending on what you need. If you need to filter queryset depending on user's input, the @SamSparx already answered you.

If you need to filter queryset based on initial form data from Trip instance, then you may override the constructor of the form and use something like this:

class EditTripForm(ModelForm):
    start_date = forms.DateField(label='Desde', widget=MyDateInput(attrs={'class': 'form-control'}))
    end_date = forms.DateField(label='Hasta', widget=MyDateInput(attrs={'class': 'form-control'}))
    operations = forms.ModelMultipleChoiceField(
        widget = forms.CheckboxSelectMultiple,
        # no query here
        queryset = OperationCard.objects.none()
    )

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        trip = self.instance
        # filter by date here
        self.fields['operations'].queryset = OperationCard\
            .order_by('-date')\
            .filter(date__gte=trip.start_date)

    class Meta:
        model = Trip
        fields = ['start_date', 'end_date', 'operations']
  • Related