我有一个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'
当地的vars params正在发送一份清单:
[u'choice_one', u'choice_two', u'choice_three']
所有表单字段都显示正确,但是当我提交POST时,我收到错误
绑定参数7时出错 - 可能是不支持的类型。
我是否需要在视图中进一步处理多选字段?模型字段类型是否正确?任何帮助或参考将不胜感激。
答案 0 :(得分:34)
需要将配置文件选项设置为ManyToManyField才能使其正常工作。
所以......你的模型应该是这样的:
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)
然后,同步数据库并使用您想要的各种选项加载Choices。
现在,ModelForm将自行构建......
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))
应该提到的是,您可以通过几种不同的方式设置配置文件,包括继承。也就是说,这对你也有用。
祝你好运。答案 1 :(得分:14)
布兰特的解决方案绝对正确,但我需要修改它以使其适用于多个选择复选框和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))
答案 2 :(得分:13)
models.CharField是其中一个选项的CharField表示。你想要的是一组选择。这似乎没有在django中实现。
你可以使用多对多字段,但缺点是选择必须放在数据库中。如果你想使用硬编码选择,这可能不是你想要的。
http://djangosnippets.org/snippets/1200/上有一个django代码段 似乎通过实施ModelField MultipleChoiceField
来解决您的问题。
答案 3 :(得分:2)
ManyToManyField 不是一个不错的选择。您可以使用一些代码段来实现 MultipleChoiceField 。您可以受到MultiSelectField with comma separated values (Field + FormField)的启发 但它有一些错误。你可以安装django-multiselectfield。这是更完美的。
答案 4 :(得分:0)
我发现的最简单的方法(只是我使用eval()将从输入中获取的字符串转换为元组,以再次读取表单实例或其他位置)
这个技巧很好用
#model.py
class ClassName(models.Model):
field_name = models.CharField(max_length=100)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if self.field_name:
self.field_name= eval(self.field_name)
#form.py
CHOICES = [('pi', 'PI'), ('ci', 'CI')]
class ClassNameForm(forms.ModelForm):
field_name = forms.MultipleChoiceField(choices=CHOICES)
class Meta:
model = ClassName
fields = ['field_name',]
答案 5 :(得分:0)
您可以使用ArrayField
轻松实现此目标:
# in my models...
tags = ArrayField(models.CharField(null=True, blank=True, max_length=100, choices=SECTORS_TAGS_CHOICES), blank=True, default=list)
# in my forms...
class MyForm(forms.ModelForm):
class Meta:
model = ModelClass
fields = [..., 'tags', ...]
我使用tagsinput JS库来呈现我的标签,但是您可以使用任何喜欢的方法: 这是此小部件的模板:
{% if not hidelabel and field.label %}<label for="{{ field.id_for_label }}">{{ field.label }}</label>{% endif %}
<input id="{{ field.id_for_label }}" type="text" name="{{ field.name }}" data-provide="tagsinput"{% if field.value %} value="{{ field.value }}"{% endif %}{% if field.field.disabled %} disabled{% endif %}>
{% if field.help_text %}<small id="{{ field.name }}-help-text" class="form-text text-muted">{{ field.help_text | safe }}</small>{% endif %}