#17137 closed Bug (invalid)
ModelForm is_valid() accepts options outside choices
Reported by: | Owned by: | Dan Poirier | |
---|---|---|---|
Component: | Forms | Version: | 1.3 |
Severity: | Normal | Keywords: | |
Cc: | Triage Stage: | Accepted | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description (last modified by )
If form is made using ModelForm
and choices of ManyToMany
field are limited like this:
# models.py class Product(models.Model): name = models.CharField(max_length=60, verbose_name="Name") visibility = models.ManyToManyField(Group, verbose_name="Groups") # views.py class ProductForm(forms.ModelForm): def __init__(self, group_choices, *args, **kwargs): super(ProductForm, self).__init__(*args, **kwargs) self.fields['visibility'].choices = group_choices class Meta: model = Product @login_required def products_view(request): userprofile = UserProfile.objects.get(user = request.user) groups = [ (i.id, i.group) for i in Membership.objects.filter(userprofile=userprofile) ] if request.method == "POST": form = ProductForm(groups, request.POST) if form.is_valid(): .. do stuff with visibility trusting form.is_valid()
is_valid()
allows values for ManyToMany
selections outside what is specified in the form as long as there exists corresponding ID in the database. Obviously the submitted form needs to be modified outside standard browser UI.
is_valid()
should compare selections against .choices, not against what exists in the database.
Change History (4)
comment:1 by , 13 years ago
Description: | modified (diff) |
---|
comment:2 by , 13 years ago
Owner: | changed from | to
---|---|
Status: | new → assigned |
comment:3 by , 13 years ago
Resolution: | → invalid |
---|---|
Status: | assigned → closed |
Triage Stage: | Unreviewed → Accepted |
From https://docs.djangoproject.com/en/dev/topics/forms/modelforms/:
ManyToManyField is represented by django.forms.ModelMultipleChoiceField, which is a MultipleChoiceField whose choices are a model QuerySet.
Validation of a ModelMultipleChoiceField is controlled by the queryset value, not choices.
comment:4 by , 13 years ago
@hayrynen I think you should try using queryset
attribute instead.
class ProductForm(forms.ModelForm): def __init__(self, visibility_qs, *args, **kwargs): super(ProductForm, self).__init__(*args, **kwargs) self.fields['visibility'].queryset = visibility_qs class Meta: model = Product @login_required def products_view(request): userprofile = UserProfile.objects.get(user = request.user) # assuming Membership.group's related_name is unset visibility_qs = Groups.objects.filter(membership_set__userprofile=userprofile) if request.method == "POST": form = ProductForm(visibility_qs, request.POST) if form.is_valid(): .. do stuff with visibility trusting form.is_valid()
Fixed formatting -- please use wiki syntax and preview.