【问题标题】:Narrowing choices in Django form缩小 Django 形式的选择范围
【发布时间】:2009-09-10 19:31:06
【问题描述】:

我有一个这样的模型:

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'}),但我找不到任何方法来为选择集执行此操作。

【问题讨论】:

  • 您可能需要更改字段名称,因为“type”是 Python 中的保留关键字。
  • 另外,您是否有任何理由不将广告系列类型设为 ChoiceField 而不是 CharField?
  • Campaign 是一个模型,所以 ChoiceField 不是一个选项。

标签: django django-forms


【解决方案1】:

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

在 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

【讨论】:

    【解决方案2】:

    选项仅适用于列表,而不适用于 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
    

    【讨论】:

    • 我不确定这到底是如何工作的。我试图在表单的选择列表中显示“电子邮件”和“显示”。
    【解决方案3】:

    这似乎是覆盖“类型”字段的最佳方法:

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

    我现在不确定如何传递“1”,但这已经足够了,即使它需要硬编码。另外,它让 Django 完成了大部分繁重的工作。

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

    【讨论】:

    • 任何有关将变量传递给 type__id 的帮助将不胜感激。在表格内部,没有“自我”。我不知道那里有什么可以访问的。
    • 这可以在实例化时使用: form = CampaignForm() form.fields['type'].choices = TestModel.objects.\ filter(filtercriterion__id=1).values_list('id' ,'名字')
    猜你喜欢
    • 2018-03-08
    • 1970-01-01
    • 2015-10-04
    • 2016-07-22
    • 1970-01-01
    • 2012-02-23
    • 1970-01-01
    • 2015-04-13
    • 1970-01-01
    相关资源
    最近更新 更多