缩小Django形式的选择

时间:2009-09-10 19:31:06

标签: django django-forms

我有一个类似的模型:

CAMPAIGN_TYPES = (
                  ('email','Email'),
                  ('display','Display'),
                  ('search','Search'),
                  )

class Campaign(models.Model):
    name = models.CharField(max_length=255)
    type = models.CharField(max_length=30,choices=CAMPAIGN_TYPES,default='display')

表格:

class CampaignForm(ModelForm):
    class Meta:
        model = Campaign

有没有办法限制“类型”字段可用的选项?我知道我可以做一个单值字段:CampaignForm(initial={'name':'Default Name'})但是我找不到任何方法来为选择集做这个。

3 个答案:

答案 0 :(得分:6)

这就是我限制显示选项的方式:

在forms.py中为表单添加 init 方法

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

答案 1 :(得分:1)

选择仅适用于列表,不适用于CharFields。您需要做的是创建custom validator on clean()

在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

答案 2 :(得分:1)

通过覆盖'type'字段,这似乎是最好的方法:

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

我现在不确定如何传递'1'但即使它需要硬编码也会很好。此外,它让Django完成了大部分繁重的工作。

@soviut我会将字段名称更改为非保留字。谢谢您的提醒。