问题
I have model with ManyToManyField. Now I need form but don't need select field in template.
class Foo(models.Model):
name = models.CharField(max_length=50)
short_description = models.CharField(max_length=100)
price = models.IntegerField()
def __unicode__(self):
return self.name
class Bar(models.Model):
foo = models.ManyToManyField(Foo, blank=True, null=True, related_name='foos')
def __unicode__(self):
return unicode(self.id)
What I really need is to display all data from the Foo model with checkboxes in template, instead of select field which I have if use model.Form and {{ form }} call in template.
class BarForm(forms.ModelForm):
class Meta:
model = Bar
view.py
def show_form(request, id):
foo = get_object_or_404(Foo, id=id)
form = BarForm()
...
回答1:
To show a ManyToManyField as checkboxes instead of a select field, you need to set the widget in the Meta class of the appropriate ModelForm subclass. Then to show a custom label on each checkbox, create your own form field class derived from ModelMultipleChoiceField, and override label_from_instance. You may also add HTML tags to the string returned by label_from_instance to make it look as pretty as you want, but remember to wrap the returned string with mark_safe.
from django.forms.widgets import CheckboxSelectMultiple
from django.forms.models import ModelMultipleChoiceField
...
class CustomSelectMultiple(ModelMultipleChoiceField):
def label_from_instance(self, obj):
return "%s: %s %s" %(obj.name, obj.short_description, obj.price)
class BarForm(forms.ModelForm):
foo = CustomSelectMultiple(queryset=Foo.objects.all())
class Meta:
model = Bar
widgets = {"foo":CheckboxSelectMultiple(),}
来源:https://stackoverflow.com/questions/8630977/manytomany-field-in-form-with-checkboxes-insted-select-field-in-django-template