How to change ForeignKey display text in the Django Admin?

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)

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.


Newer versions of django support this, which can be translated with gettext:

models.ForeignKey(ForeignStufg, verbose_name='your text')