Using fields from multiple models (connected by foreign key) in the ModelAdmin

954 views
Skip to first unread message

Eiji Kobayashi

unread,
May 7, 2011, 3:44:58 AM5/7/11
to django...@googlegroups.com
Hi!

I'm having trouble figuring out what to do.
I have multiple models linked together using foreignkey, like the following:

# models.py
class Member(User):
  middle_name = models.CharField(max_length=20)

class Phone(models.Model):
  owner = models.ForeignKey(Member)
  areacode = models.CharField(max_length=5)
  number = models.CharField(max_length=12)

class Address(models.Model):
  owner = models.ForeignKey(Member)
  address = models.CharField(max_length=50)
  city = models.CharField(max_length=50)
  state = models.CharField(max_length=30)
  zip = models.CharField(max_length=20)

I want to be able to create the form that uses all three of the models in the admin section, so I did this:

# admin.py
from django.contrib import admin
from django.contrib.auth.models import User
from models import Member, Address, Phone

class PhoneInline(admin.StackedInline):
  model = Phone
  can_delete = True
  extra = 0

class AddressInline(admin.StackedInline):
  model = Address
  can_delete = True
  extra = 0

class MemberAdmin(admin.ModelAdmin):
  inlines = [ PhoneInline, AddressInline ]
  fieldsets = (
    (None, {
        'fields': ( 'first_name', 'middle_name', 'last_name', 'areacode', 'number' )
    }),
    ('Address', {
       'fields': ( 'address', 'state', 'city', 'state', 'zip' )
    })
   )

admin.site.register(Member, MemberAdmin)

When I runserver, it throws the following error:

ImproperlyConfigured at /admin

'MemberAdmin.fields' refers to field 'areacode' that is missing from the form.

If I take out 'areacode', 'number' from the None fieldset and remove the 'Address' fieldset, leaving only
'first_name', 'middle_name', and 'last_name', it works fine. So, how can I access the fields that are linked by foreign key?
This is driving me crazy!!!

Thanks!
Eiji

Oleg Lomaka

unread,
May 7, 2011, 10:22:07 AM5/7/11
to django...@googlegroups.com
Move fields from ModelAdmin to appropriate InlineModelAdmin

#admin.py
from models import Member, Address, Phone

class PhoneInline(admin.StackedInline):
    model = Phone
    can_delete = True
    extra = 0
    fields = ('areacode', 'number')

class AddressInline(admin.StackedInline):
    model = Address
    can_delete = True
    extra = 0
    fields = ('address', 'city', 'state', 'zip')

class MemberAdmin(admin.ModelAdmin):
    inlines = [ PhoneInline, AddressInline ]
    fieldsets = (
        (None, {
                'fields': ( 'username', 'first_name', 'middle_name', 'last_name')
                }),
        )
    
admin.site.register(Member, MemberAdmin)


--
You received this message because you are subscribed to the Google Groups "Django users" group.
To post to this group, send email to django...@googlegroups.com.
To unsubscribe from this group, send email to django-users...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/django-users?hl=en.

Eiji Kobayashi

unread,
May 7, 2011, 4:59:32 PM5/7/11
to Django users
This doesn't do anything. I still get the same error.

I'd like to be able to access the fields from the Phone and Address
model from
the MemberAdmin model. I still cannot do this. Any other way?

Eiji

On May 7, 7:22 am, Oleg Lomaka <oleg.lom...@gmail.com> wrote:
> Move fields from ModelAdmin to appropriate InlineModelAdmin
>
> #admin.py
> from models import Member, Address, Phone
>
> class PhoneInline(admin.StackedInline):
>     model = Phone
>     can_delete = True
>     extra = 0
>     fields = ('areacode', 'number')
>
> class AddressInline(admin.StackedInline):
>     model = Address
>     can_delete = True
>     extra = 0
>     fields = ('address', 'city', 'state', 'zip')
>
> class MemberAdmin(admin.ModelAdmin):
>     inlines = [ PhoneInline, AddressInline ]
>     fieldsets = (
>         (None, {
>                 'fields': ( 'username', 'first_name', 'middle_name',
> 'last_name')
>                 }),
>         )
>
> admin.site.register(Member, MemberAdmin)
>

Oleg Lomaka

unread,
May 7, 2011, 11:32:21 PM5/7/11
to django...@googlegroups.com
If you get the same error, the you have missed something. Show me your current admin.py once more.

As to "I'd like to be able to access the fields from the Phone and Address model from the MemberAdmin model". You can access fields from Phone and Address from the InlineAdminModel. That is in case you want to access them on change/add view. As shown in my previous example.

And if you want to access those fields from list view, then you can create a function in your Member model to format phone fields into string and include it in a list_display. Example

# models.py
class Member(User):
  middle_name = models.CharField(max_length=20)

  def all_phones(self):
    return ", ".join(["(%s) %s" % (p.areacode, p.number) for p in self.phone_set.all()])

# admin.py
class MemberAdmin(admin.ModelAdmin):
  list_display = ('first_name', 'middle_name', 'last_name', 'all_phones')

Eiji Kobayashi

unread,
May 8, 2011, 12:19:58 AM5/8/11
to Django users
Hi Oleg,

Thanks for your patience. I'm pretty sure I DID miss something like
you said. Here's my admin.py, with the modifications you suggested:

# admin.py
from django.contrib import admin
from django.contrib.auth.models import User
from models import Member, Address, Phone

class PhoneInline(admin.StackedInline):
model = Phone
can_delete = True
extra = 0
fields = ( 'areacode', 'number')

class AddressInline(admin.StackedInline):
model = Address
can_delete = True
extra = 0
fields = ( 'addresstype', 'address', 'city', 'state', 'postal_code')

class MemberAdmin(admin.ModelAdmin):
inlines = [ PhoneInline, AddressInline ]
fieldsets = (
(None, {
'fields': ( 'first_name', 'middle_name', 'last_name',
'areacode', 'number' )
})
)

admin.site.register(Member, MemberAdmin)

The actual error I get is:

ImproperlyConfigured at /admin/
'MemberAdmin.fieldsets[0][1]['fields']' refers to field 'areacode'
that is missing from the form.

When I add the all_phones function in the models.py and define the
list_display like you suggested, I get this error:

TemplateSyntaxError at /admin/account/member/
Caught OperationalError while rendering: (1054, "Unknown column
'account_phone.areacode' in 'field list'")

There must be a simpler way to just edit the primary model and its
related models in the admin, no?
Thanks!

Eiji



On May 7, 8:32 pm, Oleg Lomaka <oleg.lom...@gmail.com> wrote:
> If you get the same error, the you have missed something. Show me your
> current admin.py once more.
>
> As to "I'd like to be able to access the fields from the Phone and
> Address model from the MemberAdmin model". You can access fields from Phone
> and Address from the InlineAdminModel. That is in case you want to access
> them on change/add view. As shown in my previous example.
>
> And if you want to access those fields from list view, then you can create a
> function in your Member model to format phone fields into string and include
> it in a list_display. Example
>
> # models.py
> class Member(User):
>   middle_name = models.CharField(max_length=20)
>
>   def all_phones(self):
>     return ", ".join(["(%s) %s" % (p.areacode, p.number) for p in
> self.phone_set.all()])
>
> # admin.py
> class MemberAdmin(admin.ModelAdmin):
>   list_display = ('first_name', 'middle_name', 'last_name', 'all_phones')
>

Oleg Lomaka

unread,
May 8, 2011, 3:00:34 AM5/8/11
to django...@googlegroups.com
You have started from the beginning. Take a look at my very first reply in this thread. Remove 'areacode' and 'number' fields from your MemberAdmin. Let them be available from PhoneInline and AddressInline. You will be see them on the same admin page, just in other visual block where inline forms display.

Sure, if you don't like such things, you are always up to extend admin template for exactly this view and output anything you like.

Eiji Kobayashi

unread,
May 8, 2011, 6:36:19 AM5/8/11
to django...@googlegroups.com
On Sun, May 8, 2011 at 12:00 AM, Oleg Lomaka <oleg....@gmail.com> wrote:
You have started from the beginning. Take a look at my very first reply in this thread. Remove 'areacode' and 'number' fields from your MemberAdmin. Let them be available from PhoneInline and AddressInline. You will be see them on the same admin page, just in other visual block where inline forms display.

Sure, if you don't like such things, you are always up to extend admin template for exactly this view and output anything you like.



Yes, maybe that'll be a good way to learn to grasp the concept of django. Thanks. 

Reply all
Reply to author
Forward
0 new messages