Django 多选字段 / 多选框选择多个
我有一个Django应用程序,想在用户的个人资料中显示多个选择的复选框。这样他们就可以选择多个项目。
这是我简化版的models.py文件:
from profiles.choices import SAMPLE_CHOICES
class Profile(models.Model):
user = models.ForeignKey(User, unique=True, verbose_name_('user'))
choice_field = models.CharField(_('Some choices...'), choices=SAMPLE_CHOICES, max_length=50)
还有我的表单类:
class ProfileForm(forms.ModelForm):
choice_field = forms.MultipleChoiceField(choices=SAMPLE_CHOICES, widget=forms.CheckboxSelectMultiple)
class Meta:
model = Profile
以及我的views.py文件:
if request.method == "POST":
profile_form = form_class(request.POST, instance=profile)
if profile_form.is_valid():
...
profile.save()
return render_to_response(template_name, {"profile_form": profile_form,}, context_instance=RequestContext(request))
我发现POST请求只发送了一个值:
choice_field u'choice_three'
而本地变量params却发送了一个列表:
[u'choice_one', u'choice_two', u'choice_three']
所有的表单字段显示都正确,但当我提交POST请求时,出现了一个错误
错误绑定参数7 - 可能是不支持的类型。
我需要在视图中进一步处理这个多选字段吗?模型字段类型正确吗?任何帮助或参考资料都将非常感激。
7 个回答
13
models.CharField 是用来表示你选择的选项之一的字符字段。你其实想要的是一组选择。看起来在 Django 中还没有实现这个功能。
你可以使用多对多字段来实现,但这样有个缺点,就是这些选择必须存储在数据库里。如果你想要的是硬编码的选择,这样做可能就不太合适了。
在这个链接 http://djangosnippets.org/snippets/1200/ 上,有一个 Django 的代码片段,似乎可以解决你的问题,它实现了一个 ModelField 的 MultipleChoiceField
。
19
Brant的解决方案是完全正确的,但我需要对它进行一些修改,以便它能与多个选择框和commit=false
一起使用。以下是我的解决方案:
models.py
class Choices(models.Model):
description = models.CharField(max_length=300)
class Profile(models.Model):
user = models.ForeignKey(User, blank=True, unique=True, verbose_name_('user'))
the_choices = models.ManyToManyField(Choices)
forms.py
class ProfileForm(forms.ModelForm):
the_choices = forms.ModelMultipleChoiceField(queryset=Choices.objects.all(), required=False, widget=forms.CheckboxSelectMultiple)
class Meta:
model = Profile
exclude = ['user']
views.py
if request.method=='POST':
form = ProfileForm(request.POST)
if form.is_valid():
profile = form.save(commit=False)
profile.user = request.user
profile.save()
form.save_m2m() # needed since using commit=False
else:
form = ProfileForm()
return render_to_response(template_name, {"profile_form": form}, context_instance=RequestContext(request))
41
为了让这个功能正常工作,个人资料的选择需要设置为多对多字段。
所以,你的模型应该像这样:
class Choices(models.Model):
description = models.CharField(max_length=300)
class Profile(models.Model):
user = models.ForeignKey(User, blank=True, unique=True, verbose_name='user')
choices = models.ManyToManyField(Choices)
接下来,更新数据库,并加载你想要的各种选项到选择中。
现在,模型表单会自动生成...
class ProfileForm(forms.ModelForm):
Meta:
model = Profile
exclude = ['user']
最后是视图部分:
if request.method=='POST':
form = ProfileForm(request.POST)
if form.is_valid():
profile = form.save(commit=False)
profile.user = request.user
profile.save()
else:
form = ProfileForm()
return render_to_response(template_name, {"profile_form": form}, context_instance=RequestContext(request))
值得一提的是,你可以用几种不同的方式来设置个人资料,包括继承。不过,这种方法对你来说也应该有效。
祝你好运。