You have your model with a fixed set of choices. Typically:
models.py
class Issue(models.Model):
type = models.CharField(max_length=1, choices=(('t', 'task'), ('b', 'bug')))
Now, in your Django admin, you want to show different choices:
admin.py
class IssueAdmin(admin.ModelAdmin):
def formfield_for_choice_field(self, db_field, request, **kwargs):
if db_field.name == "type":
kwargs['choices'] = (
('b', 'bug'),
('e', 'enhancement'),
)
return super(IssueAdmin, self).formfield_for_choice_field(db_field, request, **kwargs)
The above doesn't work when you try to save with choice "enhancement". Why? Because your model field doesn't accept your input (it doesn't contain the enchancement choice). Why, I changed the choices in the ``IssueAdmin``? Yes, well, you changed the choices in the form field (hence the formfield_for... function name) that is based on your model. You didn't change the choices on your model field.
Here's the code that allows the desired behaviour:
models.py
from django.db import models
class Issue(models.Model):
type = models.CharField(max_length=1)
admin.py
from django import forms
from django.contrib import admin
from .models import Issue
class IssueForm(forms.ModelForm):
class Meta:
model = Issue
widgets = {
'type': forms.Select(),
}
class IssueAdmin(admin.ModelAdmin):
form = IssueForm
# Note the use of formfield_for_dbfield instead of formfield_for_choice_field!
def formfield_for_dbfield(self, db_field, **kwargs):
# Add some logic here to base your choices on.
if db_field.name == 'type':
kwargs['widget'].choices = (
('b', 'bug'),
('e', 'enhancement'),
)
return super(IssueAdmin, self).formfield_for_dbfield(db_field, **kwargs)
admin.site.register(Issue, IssueAdmin)
You cannot use a ChoiceField in your form and use formfield_for_choice_field. This function actually checks whether your model field has an attribute called choices (and since it's a CharField without any choices it obviously does not have this attribute).
I also described this as answer on a Django ticket which lead me to write this blog post.
Nested resources in Tastypie MySQL AES_ENCRYPT in Python