迭代 django 表单结果(不在模板中)

Posted

技术标签:

【中文标题】迭代 django 表单结果(不在模板中)【英文标题】:iterate over django form results (not in a template) 【发布时间】:2015-04-01 19:03:00 【问题描述】:

我正在尝试迭代表单结果,我不禁认为我在这里重新发明了***。

filterlist = []

if request.POST:
        form = FilterForm(request.POST)
        if form.is_valid():
            for key, value in form.cleaned_data.iteritems():
                filterlist.append(key)
                filterlist.append(value)

这可行,但看起来很尴尬,并产生了许多其他问题。例如,值与 u' 一起返回,所以我必须使用 value.encode("utf8") 但如果值为 None 它会引发错误。所以现在我必须检查它是否为无,如果不是则编码。一定有更好的方法。

编辑:我想要做什么。

我正在尝试过滤页面上显示的内容。我遇到的问题是,如果一个值为空(用户不填写该框,因为他们只想过滤一个对象),那么我不会得到任何结果。例如,用户想要按作者姓名“Smith”搜索所有书籍,但不想搜索流派。

results = Books.objects.filter(author=author, genre=genre) 

用户不会得到任何结果,因为这是一个 AND 搜索。但是,如果用户为作者输入“Smith”,为流派输入“mystery”,那么它的工作原理与我想要的完全一样,只会给出两者都正确的结果。

所以,我试图通过迭代表单结果来消除空的东西。就像我说的那样,我可能在这里重新发明***。

【问题讨论】:

为什么必须将其转换回“普通”字符串? 更好的方法来做什么?您还没有解释为什么要这样做,或者您如何以重要的 Unicode 方式使用输出。 你到底想做什么?看起来您的 filterlist 是一个键列表,后跟值。 我编辑了我的帖子以提供更多背景信息。 您是否尝试过使用 django.db.models 中的 Q 以及将 modelForm 中的必填字段设置为 False 以使其工作class myForm(forms.ModelForm): myField = forms.CharField(required=False) class Meta: model = myModel 【参考方案1】:

我认为问题在于默认情况下,如果表单字段没有用户输入的值,则模型表单无效,如果您每次都不需要用户输入该字段,则需要设置所需的form.py 中 ModelForm 类中的字段为 false ,如下面的代码所示。请记住,该字段仅在模型表单中设置为 false,而不是在模型本身中

class myForm(forms.ModelForm):
    myfield_id = forms.CharField(required=False)
    myfield_foo = forms.CharField(required=False)
    myfield_bar = forms.CharField(required=False)
    myfield_name = forms.CharField(required=False)
    class Meta:
        model = myModel
        exclude = ('myfield_ex','myfield_file')
        fields  = ['myfield_id','myfield_foo','myfield_bar','myfield_name',]

在用户输入表单后,您需要使用 Q 对象,该对象可用于创建复杂查询,如此处的 manula 页面中所述 https://docs.djangoproject.com/en/1.7/topics/db/queries/#complex-lookups-with-q

一个简单的示例代码如下所示

if form.is_valid():
        qgroup = []
        for key,value in form.cleaned_data.iteritems():
            if value:
                q_name = Q(**"%s"%format(filterKey[key]) : value)
                qgroup.append(q_name)
        q = None
        # can use the reduce as shown here qgroup = reduce(operator.or_, (Q(**"0".format(filterKey[key]): value) for (key,value) in form.cleaned_data.iteritems()))
        for key,value in form.cleaned_data.iteritems():
            if value:
                q_name = Q(**"%s"%format(filterKey[key]) : value)
                qgroup.append(q_name)
        for x in qgroup:
                q &= x ### Or use the OR operator or 
        if q:
            resultL = myModel.objects.filter(q).select_related()

filterKey 可以看起来像

 filterKey = 'myfield_id'          : "myfield_id",
             'myfield_foo'          : "myfield_foo__icontains",
             'myfield_bar'           : "myfield_bar__relative_field__icontains",
             

【讨论】:

@Ignacio Vazquez-Abrams 这里@Ignacio Vazquez-Abrams ***.com/questions/852414/… cmidi,感谢您的回答。我确信这会起作用,如果我正在做更复杂的过滤器,我可能会使用 Q 对象。但是,我选择了 Paulo Scardine 提供的解决方案。他的解决方案更简单,符合我的需求。【参考方案2】:

如果模型和表单中的字段名称相同,请尝试以下操作:

filter = 

if request.method == 'POST':
    form = FilterForm(request.POST)
    if form.is_valid():
        for key, value in form.cleaned_data.iteritems():
            if value:
                filter[key] = value
        results = Books.objects.filter(**filter)

Python 是少数具有命名参数的语言之一。您可以使用非空表单字段组合 dict,并使用 kwargs 解包运算符 ** 将其传递给过滤器方法。

例如:

kwargs = "author": "Freud"
results = Books.objects.filter(**kwargs)

等同于:

results = Books.objects.filter(author="Freud")

【讨论】:

完美!这正是我一直在寻找的。在我看到你的答案之前,我还发现了这个blog post,它谈到了在过滤器中使用关键字参数。这就是让我爱上 python 的原因。【参考方案3】:

在 Python 3 中使用:

for key, value in form.cleaned_data.items():

【讨论】:

以上是关于迭代 django 表单结果(不在模板中)的主要内容,如果未能解决你的问题,请参考以下文章

Django:For循环迭代表单字段

我的删除模式表单总是删除数据模型中的第一个对象?(Django)

如何在不在 python 中迭代它们的情况下明显地批量更新 django 模型的所有对象?

Django - 在模板的for循环中迭代数字

如何在 django 模板中迭代字典的列表值

在 Django 模板中迭代 JSON