Администратор Django делится строками между приложениями - PullRequest
1 голос
/ 02 апреля 2011

В моем проекте есть несколько приложений, которые я хочу использовать повторно.

Во-первых, у меня есть приложение базового контента, которое определяет, как контент может быть добавлен в ContentContainer. Это позволяет другим моделям наследовать ContentContainer, чтобы получить возможность показывать контент.

В приложении контента у меня есть модель Page, которая наследует ContentContainer. В другом приложении под названием events у меня есть модель Event, которая также наследует ContentContainer. В основном, мое приложение событий зависит от моего приложения контента (что я и хочу).

Все это прекрасно работает в моделировании. У меня есть это в моем приложении контента:

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.

1 Ответ

3 голосов
/ 02 апреля 2011

Ошибка «уже зарегистрирован» возникает потому, что при импорте модуля Python выполняет все операторы на верхнем уровне - и одним из них является admin.site.register, который поэтому вызывается несколько раз.

Это легко исправить - просто поймайте исключение и проигнорируйте его:

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

Альтернативой является сохранение ваших встроенных классов в полностью отдельном файле модуля - возможно, admin_inlines.py - и их импорт оттуда вкаждый админ, который нуждается в них.

...