How to change display text in django admin foreignkey dropdown
I have a task list, with ability to assign users. So I have foreignkey to User model in the database. However, the default display is username in the dropdown menu, I would like to display full name (fir开发者_如何学Pythonst last) instead of the username. If the foreignkey is pointing to one of my own classes, I can just change the str function in the model, but User is a django authentication model, so I can't easily change it directly right?
Anyone have any idea how to accomplish this?
Thanks a lot!
You can create a new ModelForm for your Task model, which will display the list of users however you like (code here assumes a model named Task with a 'user' attribute):
def get_user_full_name_choices:
return [(user, user.get_full_name()) for user in User.objects.all()]
class TaskAdminForm(forms.ModelForm):
class Meta:
model = Task
user = forms.ChoiceField(choices=get_user_full_name_choices)
Then, tell your ModelAdmin class to use the new form:
class TaskAdmin(admin.ModelAdmin):
form = TaskAdminForm
There is another choice:
USERS = [(user.id, user.get_full_name()) for user in User.objects.all()]
USERS.insert(0, ('', '----'))
class TaskAdminForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(TaskAdminForm, self).__init__(*args, **kwargs)
self.fields['user'].choices=USERS
A more generic, verbose solution, using a ModelChoiceField as base. Avoids fiddling with querysets, just focusing on modifying the visible value in the dropdown.
- create your own formfield:
class CustomLabelChoiceField(forms.ModelChoiceField):
def label_from_instance(self, obj):
return "Howdy {}".format(obj.name)
- use it either with formfield_for_dbfield (as in the link), or, more verbose, in your admin form:
class TaskAdminForm(forms.ModelForm):
user = CustomLabelChoiceField(queryset=User.objects.all()
class Meta:
model = Task
# obviously, link it with your admin
class TaskAdmin(admin.ModelAdmin):
form = TaskAdminForm
By overriding formfield_for_foreignkey(), you can display the combination of "first_name" and "last_name" to Django Admin without creating a custom "forms.ModelChoiceField" and a custom "forms.ModelForm" as shown below:
@admin.register(Task)
class TaskAdmin(admin.ModelAdmin):
def formfield_for_foreignkey(self, db_field, request, **kwargs):
formfield = super().formfield_for_foreignkey(db_field, request, **kwargs)
if db_field.name == "user":
formfield.label_from_instance = lambda obj: f'{obj.first_name} ({obj.last_name})'
return formfield
精彩评论