Django 2.2 设置不带 id/pk 的 ModelChoiceField 初始值



我有一个基于 GET 的搜索,通过查询字符串传递一些搜索词和分页信息。我可以毫无问题地从查询字符串中获取项目,但事实证明,通过 SearchForm 将它们传回模板以保留搜索是很困难的。

items/?search=foo&category=bar&page=1&pageSize=20

forms.py

class SearchForm(forms.Form):
search = forms.CharField(*)
category = forms.ModelChoiceField(queryset=Items.objects.all(), *)

*为简洁起见,进行了简化

在视图中,我可以从查询字符串中检索所有值或其默认值,甚至可以设置搜索字段的值,但 ModelChoiceField 是我正在努力解决的问题。我可以设置一个初始值,但不能基于选择的文本......

views.py

class ItemList(View):
template_name = 'items.html'
def get(self, request):
items = Item.objects.all()
form = SearchForm()
search = request.GET.get('search')
category = request.GET.get('category')
page = int(request.GET.get('page', 1))
pageSize = int(request.GET.get('pageSize', 20))
if category != None:
#non working:
#form.fields['category'].initial = category
#working by setting a value 
form.fields['category'].initial = 1
items.filter(category__name=category)
if search != None:
form.initial['search'] = search
items = items.filter(field__icontains=search)
context = {
'form': form,
'items': items
}
return render(request, self.template_name, context)

我尝试了各种尝试从form.category字段中检索值/id的方法,但没有成功。我不想再次调用数据库来获取类别,然后从该查询中提取 id,但这似乎是唯一的事情?

我不知道我是否应该将页面和页面大小字段添加到 SearchForm 中,然后以某种方式抑制它们的显示,但我的尝试没有成功,即:

class SearchForm(forms.Form):
search = forms.CharField()
category = forms.ModelChoiceField(queryset=Items.objects.all())
page = forms.IntegerField()
pageSize = forms.IntegerField()
class Meta:
fields = ['search', 'category']
form = SearchForm(request.GET)
if form.is_valid():
#never executes

在此示例中,页面和页面大小仍显示为用户字段

我已经尝试了使用__init__构造函数设置初始值的各种解决方案,但没有成功。

希望朝着正确的方向推动,尤其是在不利用 ListView CBV 的情况下。

我想出了一种方法,不使用 to_field_name 属性返回数据库。与其名称相矛盾,设置<option>标签的值属性。

category = forms.ModelChoiceField(queryset=Category.objects.all(), *)

HTML 中的结果:

<select name="category" class="form-control w100 " id="id_category">
<option value="" selected>Category</option>
<option value="1">Category 1</option>
<option value="2">Category 2</option>
<option value="3">Category 3</option>
</select>

因此,当尝试通过以下方式在视图方法中分配初始值时:

form.fields['category'].initial = category #where category='Category 1'

它试图将value=1category进行比较,结果是空白的。

解决方案:to_field_name=属性添加到SearchForm字段声明中:

category = forms.ModelChoiceField(queryset=Category.objects.all(), to_field_name='name', *)

HTML 中的结果:

<select name="category" class="form-control w100 " id="id_category">
<option value="" selected>Category</option>
<option value="Category 1">Category 1</option>
<option value="Category 2">Category 2</option>
<option value="Category 3">Category 3</option>
</select>

使form.fields['category'].initial = categoryvalue="Category 1"category进行比较

最新更新