简体   繁体   English

Django 多项选择字段/复选框选择多项

[英]Django Multiple Choice Field / Checkbox Select Multiple

I have a Django application and want to display multiple choice checkboxes in a user's profile.我有一个 Django 应用程序,想在用户的个人资料中显示多选复选框。 They will then be able to select multiple items.然后他们将能够选择多个项目。

This is a simplified version of my models.py:这是我的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)

And my form class:还有我的表单类:

class ProfileForm(forms.ModelForm):
    choice_field = forms.MultipleChoiceField(choices=SAMPLE_CHOICES, widget=forms.CheckboxSelectMultiple)

    class Meta:
        model = Profile

And my views.py:还有我的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))

I can see that the POST is only sending one value:我可以看到 POST 只发送一个值:

choice_field u'choice_three' 

And the local vars params is sending a list:并且本地 vars params 正在发送一个列表:

[u'choice_one', u'choice_two', u'choice_three']

All of the form fields display correct, but when I submit a POST, I get an error所有表单字段都显示正确,但是当我提交 POST 时,出现错误

Error binding parameter 7 - probably unsupported type.错误绑定参数 7 - 可能不受支持的类型。

Do I need to process the multiple choice field further in the view?我是否需要在视图中进一步处理多项选择字段? Is the model field type correct?模型字段类型是否正确? Any help or references would be greatly appreciated.任何帮助或参考将不胜感激。

The profile choices need to be setup as a ManyToManyField for this to work correctly.配置文件选项需要设置为 ManyToManyField 才能正常工作。

So... your model should be like this:所以......你的模型应该是这样的:

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)

Then, sync the database and load up Choices with the various options you want available.然后,同步数据库并使用您想要的各种选项加载选项。

Now, the ModelForm will build itself...现在,ModelForm 将自行构建...

class ProfileForm(forms.ModelForm):
  Meta:
    model = Profile
    exclude = ['user']

And finally, the view:最后,观点:

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

It should be mentioned that you could setup a profile in a couple different ways, including inheritance.应该提到的是,您可以通过几种不同的方式设置配置文件,包括继承。 That said, this should work for you as well.也就是说,这也应该对你有用。

Good luck.祝你好运。

Brant's solution is absolutely correct, but I needed to modify it to make it work with multiple select checkboxes and commit=false . Brant 的解决方案是绝对正确的,但我需要修改它以使其与多个选择复选框和commit=false Here is my solution:这是我的解决方案:

models.py模型.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表格.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视图.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))

The models.CharField is a CharField representation of one of the choices. models.CharField 是其中一种选择的 CharField 表示。 What you want is a set of choices.你想要的是一组选择。 This doesn't seem to be implemented in django (yet).这似乎还没有在 django 中实现(还)。

You could use a many to many field for it, but that has the disadvantage that the choices have to be put in a database.可以为此使用多对多字段,但这样做的缺点是必须将选项放入数据库中。 If you want to use hard coded choices, this is probably not what you want.如果您想使用硬编码选择,这可能不是您想要的。

There is a django snippet at http://djangosnippets.org/snippets/1200/ that does seem to solve your problem, by implementing a ModelField MultipleChoiceField . http://djangosnippets.org/snippets/1200/上有一个 django 片段,通过实现ModelField MultipleChoiceField似乎确实解决了您的问题。

ManyToManyField 是一个不错的选择。你可以使用一些片段来实现MultipleChoiceField 。你可以受到MultiSelectField 的启发,带有逗号分隔值(Field + FormField)但是它有一些错误。你可以安装django-multiselectfield 。这是更多长官。

The easiest way I found (just I use eval() to convert string gotten from input to tuple to read again for form instance or other place)我找到的最简单的方法(只是我使用 eval() 将从输入获得的字符串转换为元组以再次读取表单实例或其他地方)

This trick works very well这个技巧效果很好

#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',]

You can easily achieve this using ArrayField :您可以使用ArrayField轻松实现这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', ...]

I use tagsinput JS library to render my tags but you can use whatever you like: This my template for this widget:我使用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 %}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM