开发者

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.

  1. create your own formfield:
class CustomLabelChoiceField(forms.ModelChoiceField):
     def label_from_instance(self, obj):
         return "Howdy {}".format(obj.name)
  1. 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
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜