10

I belive that the answer to my problem is simple, but I can't find it anywhere. Here is my predicament. I have two models: Member and MemberDetail, which are in oneToOne relation like this:

class Member(models.Model):
   ID = models.AutoField(primary_key=True)
   FIRST_NAME = models.CharField('First name', max_length=50)
   LAST_NAME = models.CharField('Last name', max_length=50)
   def __unicode__(self):  
      return u'%s %s' % (self.FIRST_NAME, self.LAST_NAME)

class MemberDetail(models.Model):
   member = models.OneToOneField(Member, primary_key=True)
   DATE_OF_BIRTH = models.DateField('Date of birth')
   EMAIL = models.EmailField('E-mail')
   PHONE = models.CharField('Phone', max_length=15)

Now in my admin.py I want to show table for member with all of his data, like this:

class MemberDetailInline(admin.TabularInline):
    model = MemberDetail

class MemberAdmin(admin.ModelAdmin):
    list_display = ("FIRST_NAME", "LAST_NAME", "date_of_birth", "email", "phone")
    inlines = [
        MemberDetailInline,
    ]

admin.site.register(Member, MemberAdmin)

I simply don't know how to write "date_of_birth", "email" and "phone" part of list_display. The closest thing I could do is adding this after inlines:

def date_of_birth(self, MemberDetail):
    return MemberDetail.DATE_OF_BIRTH
def date_of_birth(self, MemberDetail):
    return MemberDetail.EMAIL
def date_of_birth(self, MemberDetail):
    return MemberDetail.PHONE

but the fields showed empty on page. What is the solution? Thanks.

sninja
  • 401
  • 1
  • 6
  • 14

3 Answers3

18

Finally!!! I solved it. As I thought it was simple, but I had to do it other way around and with multi table inheritance:

models.py
class Member(models.Model):
    ID = models.AutoField(primary_key=True)
    FIRST_NAME = models.CharField('First name', max_length=50)
    LAST_NAME = models.CharField('Last name', max_length=50)

# Using multi table inheritance - automaticly creates one to one field
class MemberDetail(Member):
    DATE_OF_BIRTH = models.DateField('Date of birth')
    EMAIL = models.EmailField('E-mail')
    PHONE = models.CharField('Phone', max_length=15)

Now for admin.py

admin.py
class MemberDetailAdmin(admin.ModelAdmin):
    list_display = ("FIRST_NAME", "LAST_NAME", "DATE_OF_BIRTH", "EMAIL", "PHONE")

admin.site.register(MemberDetail, MemberDetailAdmin)

That's it. Maybe, there is other solutions, but this is good for me.

sninja
  • 401
  • 1
  • 6
  • 14
0

In case anyone stumbles into this question/problem, I don't know a direct way to access fields from a OneToOne relationship, however, I was able to fix the problem with the following snippet. Notice that I CAN access OneToOne fields in list_filter by using two '_' to access fields of an OneToOne, for example: modelB_fieldOne.

@admin.display(description='Date')
    def transaction_date(self, purchase):
        return purchase.transaction.date

list_display = ('product', 'transaction_date')
list_filter = ('product', 'transaction__date')

Juan Pablo
  • 71
  • 2
-1

You should just be able to do 'member_detail__email', etc. in list_display

Since it's a 1-1 you should have a backref, and associated fields are referenced using two underscores.

Colleen
  • 23,899
  • 12
  • 45
  • 75
  • 5
    Thanks for replay. I'm confused by 'member_detail__email' part. I tried, but if I put it Django reports error that is not a callable or an attribute of 'MemberAdmin' or found in the model 'Member'. I found some code that looks like a solution. It goes like Member.objects.get(), but I don't know how to complet it. – sninja Jan 15 '13 at 17:10
  • what options do you get? Usually it gives you a list. – Colleen Jan 15 '13 at 18:45
  • Another dead end. Says too many values to get or something like that. I like your idea with backref, but just don't get it how to write it. I want solution to be elegant, for example: Member__MemberDetail__EMAIL. But if it's out of "" error and if it's inside "" error. Maybe I'm missing something. The point is that Member doesn't register MemberDetail. It does on admin add form or change form. But in list_display I can't show those fields from MemberDetail. – sninja Jan 15 '13 at 19:09
  • "too many values"...? I meant, when it gave you the "not a callable or an attribute" error, it usually goes on to say "available fields are " Did it do that? – Colleen Jan 15 '13 at 19:54
  • Sorry for missunderstanding. But no, no such message. – sninja Jan 15 '13 at 20:01