Django Multiple Choice Field / Checkbox Select Multiple

前端 未结 6 1145
清酒与你
清酒与你 2020-11-29 18:09

I have a Django application and want to display multiple choice checkboxes in a user\'s profile. They will then be able to select multiple items.

This is a simplifi

相关标签:
6条回答
  • 2020-11-29 18:57

    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)

    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',]
    
    0 讨论(0)
  • 2020-11-29 19:04

    Brant's solution is absolutely correct, but I needed to modify it to make it work with multiple select checkboxes and commit=false. Here is my solution:

    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))
    
    0 讨论(0)
  • 2020-11-29 19:05

    The profile choices need to be setup as a ManyToManyField for this to work correctly.

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

    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.

    0 讨论(0)
  • 2020-11-29 19:06

    You can easily achieve this using 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:

    {% 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 %}
    
    0 讨论(0)
  • 2020-11-29 19:08

    ManyToManyField isn`t a good choice.You can use some snippets to implement MultipleChoiceField.You can be inspired by MultiSelectField with comma separated values (Field + FormField) But it has some bug in it.And you can install django-multiselectfield.This is more prefect.

    0 讨论(0)
  • 2020-11-29 19:14

    The models.CharField is a CharField representation of one of the choices. What you want is a set of choices. This doesn't seem to be implemented in django (yet).

    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.

    0 讨论(0)
提交回复
热议问题