8

Here is a snippet of models.py

class Applicant(models.Model):
    name = models.CharField(...)
    email = models.CharField(...)

class Application(models.Model):
    applicant = models.ForeignKey(Applicant)
    text = models.TextField(...)

Here is my admin.py:

class ApplicationAdmin(model.ModelAdmin):
    list_display = ['text', *******]

admin.site.register(Application, ApplicationAdmin)

In the ApplicationAdmin I want to present the Applicants name and email.

What have you tried before asking SO?
I have looked at the following code, which does not work:

list_display = ['text', 'applicant__name','applicant__email']

I have looked at ModelAdmin.inlines but as one can see, the parent/child relationship have to be reversed.

Any suggestions? How can I display an applicants name/email in Applications admin. Prefferably without migrating the database with new fields etc.

hermansc
  • 728
  • 8
  • 20
  • Possible duplicate of [Can "list\_display" in a Django ModelAdmin display attributes of ForeignKey fields?](http://stackoverflow.com/questions/163823/can-list-display-in-a-django-modeladmin-display-attributes-of-foreignkey-field) – Vlad Schnakovszki May 28 '16 at 12:00

2 Answers2

15

You can do it like the fourth possibility in the list_display docs. Just add a method to your Application model like so:

class Application(models.Model):
    applicant = models.ForeignKey(Applicant)
    text = models.TextField(...)

    def applicant_name(self):
        return self.applicant.name
    applicant_name.short_description = 'Applicant Name'

    def applicant_email(self):
        return self.applicant.email
    applicant_email.short_description = 'Applicant Email'

And then you can setup your ModelAdmin like so:

class ApplicationAdmin(model.ModelAdmin):
    list_display = ['text', 'applicant_name', 'applicant_email']
meshantz
  • 1,566
  • 10
  • 17
  • Yep... The accepted solution got edited while I was posting this. Good luck with your models! – meshantz Feb 01 '11 at 23:36
  • this is probably the better way – Thai Tran Mar 05 '13 at 13:56
  • The answer is fine. But can someone tell what actually happens when applicant_name is called during list display. Is their a separate db call made to retrieve applicant_name. – somsgod Dec 12 '19 at 12:00
  • I don't actually know what the admin does anymore. To answer a question like that, [django-debug-toolbar](https://django-debug-toolbar.readthedocs.io/en/latest) is your friend. Even if it does make separate calls, you can probably leverage [select-related](https://docs.djangoproject.com/en/3.0/ref/models/querysets/#select-related) or [prefetch-related](https://docs.djangoproject.com/en/3.0/ref/models/querysets/#prefetch-related) somehow, depending on your use case. – meshantz Dec 12 '19 at 16:09
0

If you only need to display it in list:

class Applicant(models.Model):
    name = models.CharField(...)
    email = models.CharField(...)

    def __unicode__(self):
        return "%s <%s>" % (self.name, self.email)

class ApplicationAdmin(model.ModelAdmin):
    list_display = ['text', 'applicant']

Answer to your comment

but would like to have each field as a new line/row in the admin, not as a string.

Not sure if it is the best solution availabe but it will work:

class Application(models.Model):

    @property
    def applicant__name(self):
        return self.applicant.name

    # or maybe:

    def __getattr__(self, name):
        if name.startswith('applicant__'):
            return gettattr(self.applicant, 
                            name[len('applicant__'):])
        raise AttributeError()

class ApplicationAdmin(model.ModelAdmin):
    list_display = ['text', 'applicant__name']
Ski
  • 14,197
  • 3
  • 54
  • 64
  • Will work as a alternative if there is not another solution, but would like to have each field as a new line/row in the admin, not as a string. Thanks for your answer, deeply appriciated. – hermansc Feb 01 '11 at 21:34
  • Did not try your "maybe" solution. But the other one works like a charm, even without "property". – hermansc Feb 01 '11 at 22:38