迭代 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)