Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reverse Inlines in Django Admin with more than one model

Tags:

python

django

Say I have some django models, something like this:

class Address(models.Model):
    pass

class Person(models.Model):
    address = models.ForeignKey(Address)

class Store(models.Model):
    address = models.ForeignKey(Address)

class Company(models.Model):
    address = models.ForeignKey(Address)

So, in the Admin interface, I'd like to be able to edit a Person and have the Address in-lined.

I know it's possible to do this,

class Address(models.Model):
    person  = models.ForeignKey(Person, blank=True)
    store   = models.ForeignKey(Store, blank=True)
    company = models.ForeignKey(Company, blank=True)

class Person(models.Model):
    pass

class Store(models.Model):
    pass

class Company(models.Model):
    pass

Then I can do the usual,

class AddressInline(admin.TabularInline):
    model = Address

class PersonAdmin(admin.ModelAdmin):
    model = Person
    inlines = (AddressInLine,)

class CompanyAdmin(admin.ModelAdmin):
    and so on

But this then means that I'd have more than one address per person, and my Address model doesn't feel right any more.

Any help will be appreciated.

like image 480
Dale O'Brien Avatar asked Dec 22 '11 00:12

Dale O'Brien


2 Answers

Try the following

from django.db import models
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes import generic

class Address(models.Model):
    object_id    = models.PositiveIntegerField()
    content_type = models.ForeignKey(ContentType)
    of           = generic.GenericForeignKey('content_type', 'object_id' )

class Person(models.Model):
    pass

class Store(models.Model):
    pass

class Company(models.Model):
    pass

Then you can do this:

from django.contrib import admin
from django.contrib.contenttypes import generic

class AddressInline(generic.GenericStackedInline):
    model   = Address
    max_num = 1

class PersonAdmin(admin.ModelAdmin):
    model = Person
    inlines = (AddressInLine,)

class CompanyAdmin(admin.ModelAdmin):
    and so on

admin.site.register(Person, PersonAdmin)
like image 77
Bulkan Avatar answered Oct 16 '22 02:10

Bulkan


Changing class AddressInline(admin.TabularInline) to class AddressInline(admin.StackedInline) will make the Address inline look less like it's possible to have several.

Set AddressInline.max_num to 1 if you want no more than 1 address per AddressInline.

Set AddressInline.extra to 1 if you want a blank address form when there is no related Address.

Documentation: https://docs.djangoproject.com/en/dev/ref/contrib/admin/#inlinemodeladmin-options

like image 22
jpic Avatar answered Oct 16 '22 01:10

jpic