Django 管理员在应用程序之间共享内联

发布于 2024-10-28 13:30:59 字数 2266 浏览 0 评论 0原文

我的项目中有一些我希望可重用的应用程序。

首先,我有一个基本内容应用程序,它定义了如何将内容添加到 ContentContainer。这使得其他模型可以继承ContentContainer来获得显示内容的能力。

在内容应用程序中,我有一个继承 ContentContainer 的页面模型。在另一个名为 events 的应用程序中,我有一个也继承 ContentContainer 的 Event 模型。基本上,我的活动应用程序取决于我的内容应用程序(这就是我想要的)。

这一切在建模中都非常有效。我的内容应用程序中有这个:

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

然后在我的事件应用程序中我这样做:

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']

所以现在事件可以有要呈现的内容。

这就是事情变得混乱的地方。我在内容应用程序的 admin.py 中定义了大量内联。他们在那里工作得很好。另外,如果我将它们复制并粘贴到事件应用程序中的 admin.py 中,它们也会在那里工作。

但是,我不想重复代码。我想将内联从 admin.py 导入 events.py 在内容 admin.py 中我有这个:

class TextContentInline(admin.TabularInline):
    model = models.TextContent
    extra = 1

class PageAdmin(ContainerAdmin):
    model = models.Page
    inlines = [LinkContentInline, TextContentInline]

有很多这样的内联。如何在我的 admin.py 模型之间共享它们?如果我尝试将它们导入事件 admin.py 中,我会收到一条错误消息“模型页面已注册”。我已经尝试了大约 5 种我能想到的不同的方法,但没有一个有效。我想知道是否没有办法做到这一点。哦,我也在使用 Django 1.3。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

淡水深流 2024-11-04 13:30:59

发生“已注册”错误是因为导入模块时,Python 会执行顶层的所有语句 - 其中之一是 admin.site.register,因此会被多次调用。

解决这个问题很容易 - 只需捕获异常并忽略它:

try:
    admin.site.register(MyModel, MyModelAdmin)
except admin.sites.AlreadyRegistered:
    pass

另一种方法是将内联类保存在完全独立的模块文件中 - 也许是 admin_inlines.py - 并将它们从那里导入到每个管理员中需要他们。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文