How to change ForeignKey display text in the Django Admin?
Another way of doing so (useful when you change your queryset):
class MyForm(forms.Form):
def __init__(self, *args, **kwargs):
super(MyForm, self).__init__(*args, **kwargs)
self.fields['user'].queryset = User.objects.all()
self.fields['user'].label_from_instance = lambda obj: "%s %s" % (obj.last_name, obj.first_name)
'user'
is the name of field you want to override. This solution gives you one advantage: you can override queryset as well (e.g. you want User.objects.filter(username__startswith='a')
)
Disclaimer: solution found on http://markmail.org/message/t6lp7iqnpzvlt6qp and tested.
If you want it to take effect only in admin, and not globally, then you could create a custom ModelChoiceField
subclass, use that in a custom ModelForm
and then set the relevant admin class to use your customized form.
Using an example which has a ForeignKey to the Person
model used by @Enrique:
class Invoice(models.Model):
person = models.ForeignKey(Person)
....
class InvoiceAdmin(admin.ModelAdmin):
form = MyInvoiceAdminForm
class MyInvoiceAdminForm(forms.ModelForm):
person = CustomModelChoiceField(queryset=Person.objects.all())
class Meta:
model = Invoice
class CustomModelChoiceField(forms.ModelChoiceField):
def label_from_instance(self, obj):
return "%s %s" % (obj.first_name, obj.last_name)
Newer versions of django support this, which can be translated with gettext:
models.ForeignKey(ForeignStufg, verbose_name='your text')
You can also accomplish this straight from your admin.ModelAdmin
instance using label_from_instance
. For example:
class InvoiceAdmin(admin.ModelAdmin):
list_display = ['person', 'id']
def get_form(self, request, obj=None, **kwargs):
form = super(InvoiceAdmin, self).get_form(request, obj, **kwargs)
form.base_fields['person'].label_from_instance = lambda inst: "{} {}".format(inst.id, inst.first_name)
return form
admin.site.register(Invoice, InvoiceAdmin)