【问题标题】:How do I filter values in a Django form using ModelForm?如何使用 ModelForm 过滤 Django 表单中的值?
【发布时间】:2011-03-01 22:18:22
【问题描述】:

我正在尝试使用 ModelForm 添加我的数据。它运行良好,除了 ForeignKey 下拉列表显示所有值,我只希望它显示与登录用户相关的值。

这是我的 ExcludedDate 模型,我要添加的记录:

class ExcludedDate(models.Model):
    date = models.DateTimeField()
    reason = models.CharField(max_length=50)
    user = models.ForeignKey(User)
    category = models.ForeignKey(Category)
    recurring = models.ForeignKey(RecurringExclusion)

    def __unicode__(self):
        return self.reason

这是类别的模型,它是包含我想按用户限制的关系的表:

class Category(models.Model):
    name = models.CharField(max_length=50)
    user = models.ForeignKey(User, unique=False)

    def __unicode__(self):
        return self.name

最后是表单代码:

class ExcludedDateForm(ModelForm):

    class Meta:
        model = models.ExcludedDate
        exclude = ('user', 'recurring',)

如何让表单仅显示 category.user 等于登录用户的类别子集?

【问题讨论】:

    标签: python django django-forms


    【解决方案1】:

    您可以在 init

    中自定义表单
    class ExcludedDateForm(ModelForm):
        class Meta:
            model = models.ExcludedDate
            exclude = ('user', 'recurring',)
        def __init__(self, user=None, **kwargs):
            super(ExcludedDateForm, self).__init__(**kwargs)
            if user:
                self.fields['category'].queryset = models.Category.objects.filter(user=user)
    

    在视图中,在构建表单时,除了标准表单参数外,您还将指定当前用户:

    form = ExcludedDateForm(user=request.user)
    

    【讨论】:

    • 这很有效!我不仅感谢您的回复,还感谢您回答的完整性。
    • 所以....虽然表单现在看起来很棒,但更改破坏了添加数据的视图。有任何想法吗? (代码如下)
    • def exclude_date_add(request): print(request.user) if request.method == 'POST': exclude_date = ExcludedDate(user=request.user) form = ExcludedDateForm(request.POST, instance= exclude_date) print("before if") print(request.user) if form.is_valid(): print("after if") exclude_date = form.save() return HttpResponseRedirect('/excluded_dates/') else: form = ExcludedDateForm (user=request.user) return render_to_response('excluded_date_form.html', {'form': form})
    • @malandro95:当您使用 request.POST 创建表单实例时,您似乎没有传入用户。
    • 不要忘记查看其他答案,因为通常有不止一种方法可以更好地满足您的特定情况。
    【解决方案2】:

    我知道这是旧的;但它是最早的 Google 搜索结果之一,所以我想我会添加我发现的方法。

    class CustomModelFilter(forms.ModelChoiceField):
        def label_from_instance(self, obj):
            return "%s %s" % (obj.column1, obj.column2)
    
    class CustomForm(ModelForm):
        model_to_filter = CustomModelFilter(queryset=CustomModel.objects.filter(active=1))
    
        class Meta:
            model = CustomModel
            fields = ['model_to_filter', 'field1', 'field2']
    

    其中 'model_to_filter' 是“CustomModel”模型的外键

    为什么我喜欢这种方法: 在“CustomModelFilter”中,您还可以更改模型对象在创建的 ChoiceField 中显示的默认方式,就像我在上面所做的那样。

    【讨论】:

    • 是否应该更改 column1 和 column2?
    【解决方案3】:

    这里的例子:

    models.py

    class someData(models.Model):
        name = models.CharField(max_length=100,verbose_name="some value")
    
    class testKey(models.Model):
        name = models.CharField(max_length=100,verbose_name="some value")
        tst = models.ForeignKey(someData)
    
    class testForm(forms.ModelForm):
        class Meta:
            model = testKey
    

    views.py

    ...
    ....
    ....
        mform = testForm()
        mform.fields["tst"] = models.forms.ModelMultipleChoiceField(queryset=someData.objects.filter(name__icontains="1"))
    ...
    ...
    

    或者你可以试试这样的:

    class testForm(forms.ModelForm):
        class Meta:
            model = testKey
    
    def __init__(self,*args,**kwargs):
        super (testForm,self ).__init__(*args,**kwargs)
        self.fields['tst'].queryset = someData.objects.filter(name__icontains="1")
    

    【讨论】:

    • 这可能会奏效,但这是一种不好的做法。您不应该在表单类之外破解表单。在 init 中定义这个逻辑要简单得多
    猜你喜欢
    • 1970-01-01
    • 2012-04-29
    • 2010-09-22
    • 2013-09-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多