Opened 13 years ago
Closed 11 years ago
#18168 closed Bug (fixed)
formfield_for_choice_field() doesn't validate choices updated in method
Reported by: | Owned by: | nobody | |
---|---|---|---|
Component: | contrib.admin | Version: | 1.3 |
Severity: | Normal | Keywords: | admin, inlines |
Cc: | Triage Stage: | Accepted | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
Having field declared in model:
element = models.CharField(max_length=500, verbose_name=_('admin element'), choices=(('foo', 'bar'),))
and that function in admin:
class AdminModuleElementInline(admin.StackedInline): model = AdminModuleElement def formfield_for_choice_field(self, db_field, request=None, **kwargs): if db_field.name == 'element': kwargs['choices'] = ( ('accepted', 'Accepted'), ('denied', 'Denied'), ) return db_field.formfield(**kwargs)
when I try to save it I get an error:
Value u'accepted' is not a valid choice.
So it updates the list, but validator checks the choices declared in model.
Attachments (1)
Change History (9)
comment:1 by , 13 years ago
Keywords: | admin inlines added |
---|---|
Summary: | formfield_for_choice_field() doesn't update choices declared in model → formfield_for_choice_field() doesn't validate choices declared in model |
comment:2 by , 13 years ago
Summary: | formfield_for_choice_field() doesn't validate choices declared in model → formfield_for_choice_field() doesn't validate choices updated in method |
---|
comment:3 by , 13 years ago
comment:5 by , 12 years ago
Triage Stage: | Unreviewed → Accepted |
---|
There is no traceback -- the validation error is displayed in the admin.
The reporter's example uses inlines. I could reproduce the issue with the following code. Screenshot attached.
# models.py from django.db import models1 class Variable(models.Model): NAME_CHOICES = ( ('foo', 'foo'), ('bar', 'bar'), ('baz', 'baz'), ) name = models.CharField(max_length=3, choices=NAME_CHOICES) # admin.py from django.contrib import admin from .models import Variable class VariableAdmin(admin.ModelAdmin): def formfield_for_choice_field(self, db_field, request, **kwargs): if db_field.name == "name": kwargs['choices'] = ( ('quux', 'quux'), ('quuux', 'quuux'), ) return super(VariableAdmin, self).formfield_for_choice_field(db_field, request, **kwargs) admin.site.register(Variable, VariableAdmin)
I don't think it makes sense to allow in the form values that aren't allowed by the model. If I understand correctly this method can only be used to restrict changes, not to extend them. If that's true, it should be mentioned in the documentation of formfield_for_choice_field.
by , 12 years ago
Attachment: | Screen Shot 2012-07-15 at 21.59.02.png added |
---|
comment:6 by , 12 years ago
This would limit the flexibility of the formfield_for_choice_field
function quite a bit, which I find unfortunate.
Adding arbitrary values to the choices is not wrong, since they are added to the "choices" and therefore not incorrect as a choice. It would be different if you change choices through some Javascript and let Django accept it.
I don't think it makes sense to allow in the form values that aren't allowed by the model
The choice fields (often on top of database CharField or IntegerField) do no enforce any referential integrity anyway. One can simply remove one of the choices in the code and the database nor the Django admin (for reading at least) would complain, which is the correct behavior.
As a workaround, you overriding YourForm.__init___
and use your custom form in the ModelAdmin
which adjusts your choices (depends a bit on what you need to base your choices on).
comment:7 by , 11 years ago
hitting an unrelated issue in some of this same code, and figured I'd address this. The best fix for now is to clarify that model choices and their validation always trump form choices.
There are a number of places where this can cause a trip up, but I'm going to go with a fix for this as a doc note.
comment:8 by , 11 years ago
Resolution: | → fixed |
---|---|
Status: | new → closed |
any workaround for this issue ?