trouselife
trouselife

Reputation: 969

Filter Django ModelForm without validating it

I have a form which I would like to filter based on information passed by another form, but without validating it just yet:

forms.py:

class SampleRunSearchForm(forms.ModelForm):

    class Meta:
        model = SampleRun
        fields = ('id',)

    def __init__(self, sr_obj, *args, **kwargs):
        super(SampleRunSearchForm, self).__init__(*args, **kwargs)

        self.fields['id'] = forms.ChoiceField(required=True,
                        label='Sample:',
                        widget=forms.CheckboxSelectMultiple,
                        choices=((s.id, s) for s in sr_obj)
                    )
        self.helper = FormHelper()
        self.helper.layout = Layout(
                Field('id', css_class='sample-run-display',),
                Submit('submit', 'Report samples', css_class='upload-btn')
            )
        self.helper.form_method = 'POST'

views.py:

class SearchSampleRun(View):

    samplerunform = SampleRunSearchForm
    template_name = 'results/samplerun_search_form.html'

    def get(self, request, *args, **kwargs):

        self.run_obj = get_object_or_404(Run, id=kwargs['run_id'])
        self.choice = kwargs['choice']

        self.sample_run_obj = self.obtainCorrectSamples()
        samplerunform = self.samplerunform(sr_obj=self.sample_run_obj)

        context = {'samplerunform': samplerunform}

        return render(request, self.template_name, context)


    def post(self, request, *args, **kwargs):

        samplerunform = self.samplerunform(request.POST)
        if samplerunform.is_valid(): 
             HttpResponseRedirect(...somewhere to display information)

        context = {}

        return render(request, self.template_name, context)

The initial form (not shown) takes a charfield and redirects to my SearchSampleRun view with **kwargs. I want to filter my SampleRunSearchForm based on these kwargs and display a list of check boxes - filtered model object from the SampleRun model. This works, but when i click these buttons, and submit the form, it initialised again, and sr_obj is None, so the form field produces an error.

I have tried using:

sr_obj = kwargs.pop('sr_obj', None)

In my init() method, but these must be a way to dynamically filter a form queryset in order to display a subset of values, before validating, with a view to validating when this form is submitted?

Upvotes: 0

Views: 43

Answers (1)

neverwalkaloner
neverwalkaloner

Reputation: 47374

Just add validation to the __init__ method and override id fields only if sr_objis not empty:

def __init__(self, sr_obj, *args, **kwargs):
    super(SampleRunSearchForm, self).__init__(*args, **kwargs)
    if sr_obj:
        self.fields['id'] = forms.ChoiceField(required=True,
                        label='Sample:',
                        widget=forms.CheckboxSelectMultiple,
                        choices=((s.id, s) for s in sr_obj)
                    )
    self.helper = FormHelper()
    self.helper.layout = Layout(
            Field('id', css_class='sample-run-display',),
            Submit('submit', 'Report samples', css_class='upload-btn')
        )
    self.helper.form_method = 'POST'

Upvotes: 1

Related Questions