Reputation: 3502
I have a few apps in my project that I want to be reusable.
First, I have a base content App, which defines how content can be added to a ContentContainer. This allows other models to inherit ContentContainer to get the ability to show content.
Within the content app, I have a Page model that inherits ContentContainer. In another app called events, I have an Event model that also inherites ContentContainer. Basically, my events app depends on my content app (Which is what I want).
This all works great in modeling. I have this in my content app:
class ContentContainer(admin.ModelAdmin):
#No fields, it just gets referred to by ContentItem
class Meta:
ordering = ['modified']
class ContentItem(TimeStampedModel):
name = models.CharField(max_length=1500)
page_order = models.IntegerField()
container = models.ForeignKey(ContentContainer, blank=True)
#make inheritance know the model type
objects = InheritanceManager()
class Meta:
ordering = [ 'page_order', 'modified', 'name']
def __unicode__(self):
return self.name
def render(self):
return self.name
class TextContent(ContentItem):
text = models.CharField(max_length=5000000)
def render(self):
return '<p>%s</p>' % self.text
Then in my Events app I do this:
class Event(AnnouncementBase, Addressable, ContentContainer):
cost = CurrencyField(decimal_places=2, max_digits=10, blank=True, default=0.00)
start_date = models.DateField(default = datetime.now().date())
start_time = models.TimeField(default = datetime.now().time())
end_date = models.DateField(blank=True, default=None, null = True)
end_time = models.TimeField(blank=True, default=None, null = True)
rsvp_deadline = models.DateTimeField(blank=True, default=None, null = True)
class Meta:
ordering = ['start_date', 'start_time', 'title']
So now events can have content to render.
Here's where things get confusing. I have a slew of inlines defined in admin.py in the content app. They work great there. Also, if I copy an paste them into admin.py in the events app they work there too.
However, I don't want to duplicate code. I want to import the inlines from admin.py into events.py In contents admin.py I have this:
class TextContentInline(admin.TabularInline):
model = models.TextContent
extra = 1
class PageAdmin(ContainerAdmin):
model = models.Page
inlines = [LinkContentInline, TextContentInline]
There are a bunch of these inlines. How can I share them between my admin.py models? If I try to import them in the events admin.py I get an error that says "The model Page is already registered". I've tried about 5 different things I could think of an none of them work. I am wondering if there is no way to do this. Oh I'm using Django 1.3 too.
Upvotes: 1
Views: 652
Reputation: 599590
The "already registered" error happens because when a module is imported, Python executes all the statements in the top level - and one of those is the admin.site.register
, which is therefore called multiple times.
It's easy to fix this - just catch the exception and ignore it:
try:
admin.site.register(MyModel, MyModelAdmin)
except admin.sites.AlreadyRegistered:
pass
An alternative is to keep your inline classes in a completely separate module file - admin_inlines.py
, perhaps - and import them from there into every admin that needs them.
Upvotes: 3