[Django]-Narrowing choices in Django form

6πŸ‘

βœ…

This is how I limited the options displayed:

In forms.py add an init method for your form

class TaskForm(forms.ModelForm):
    ....

    def __init__(self, user, *args, **kwargs):
        '''
        limit the choice of owner to the currently logged in users hats
        '''

        super(TaskForm, self).__init__(*args, **kwargs)

        # get different list of choices here
        choices = Who.objects.filter(owner=user).values_list('id','name')
        self.fields["owner"].choices = choices
πŸ‘€PhoebeB

1πŸ‘

Choices are for lists only, not CharFields. What you need to do is create a custom validator on clean().

in forms.py

CAMPAIGN_TYPES = ('email', 'display', 'search')

# this would be derived from your Campaign modelform
class EnhancedCampaignForm(CampaignForm):
    # override clean_FIELD
    def clean_type(self):
        cleaned_data = self.cleaned_data
        campaign_type = cleaned_data.get("type")

        # strip whitespace and lowercase the field string for better matching
        campaign_type = campaign_type.strip().lower()

        # ensure the field string matches a CAMPAIGN_TYPE, otherwise 
        # raise an exception so validation fails
        if not campaign_type in CAMPAIGN_TYPE:
            raise forms.ValidationError("Not a valid campaign type.")

        # if everything worked, return the field's original value
        return cleaned_data
πŸ‘€Soviut

1πŸ‘

It seems that this is the best way to do it by overriding the β€˜type’ field:

class CampaignForm(ModelForm):
    type = forms.ModelChoiceField(queryset=OtherModel.objects.filter(type__id=1))
    class Meta:
        model = Campaign

I’m not sure right now how to pass β€˜1’ but this will be good enough even if it needs to be hardcoded. Plus, it lets Django do most of the heavy lifting.

@soviut I will change the field name to a non-reserved word. Thanks for the heads up.

πŸ‘€Adam Nelson

Leave a comment