Наследование Джанго и постоянные ссылки - PullRequest
2 голосов
/ 05 июля 2010

Я создаю простую CMS в django с несколькими «модулями» (каждый как приложение django).Я настроил следующие модели:

class FooObject(models.Model):
    id = models.SlugField(primary_key=True)
    name = models.CharField(max_length=255)
    creator = models.ForeignKey(auth.models.User, editable=False, related_name="createdby")

class FooPage(FooObject):
    content = models.TextField(blank=True, null=True)

    @models.permalink
    def get_absolute_url(self):
        return ('page', (), {'page_id':self.id}

class FooSubitem(FooObject):
    parent = models.ForeignKey(FooPage, related_name='subitems')

В каждом из модулей я создаю подкласс FooPage и по крайней мере один подкласс FooSubitem, например,

# in FooBlog.models
class FooBlog(FooPage):
    owner = models.ForeignKey(auth.models.User, editable=False)

    @models.permalink
    def get_absolute_url(self):
        return ('blog', (), {'blog_id':self.id})

class FooPost(FooSubitem):
    post_time = models.DateTimeField(auto_now_add=True)

и

# in FooGallery.models
class FooGallery(FooPage):
    location = models.CharField(max_length=255)

    @models.permalink
    def get_absolute_url(self):
        return ('gallery', (), {'gallery_id':self.id})

class FooImage(FooSubitem):
    image_file = models.ImageField(upload_to='foogallery')

Это упрощения, но они должны дать вам хорошее представление о том, что я пытаюсь сделать.В администраторах для FooPost и FooImage я ограничиваю родительский список выбора соответствующими родительскими страницами.

Моя проблема возникает, когда я пытаюсь использовать их в шаблоне.В каждом представлении у меня есть следующее:

page_list = FooPage.objects.all()

, которое возвращает список всех FooPages, обоих типов FooBlog и FooGallery.Однако, когда я перебираю этот список:

{% for page in page_list %}{{ page.get_absolute_url }}{% endfor %}

он возвращает шаблон URL страницы, а не шаблон URL блога или галереи.

Как мне это сделатьработать без необходимости переписывать код, когда я хочу добавить модуль FooCalendar позже?Я хочу убедиться, что это работает с любым возможным модулем.

Спасибо,

  • Lexo

Ответы [ 3 ]

2 голосов
/ 06 июля 2010

Классическим решением этой проблемы обычно является добавление ContentType к суперклассу, который хранит тип подкласса для этого экземпляра .Таким образом, вы можете положиться на непротиворечивый API, который возвращает связанный объект подкласса соответствующего типа.

1 голос
/ 11 января 2013

Вы можете избежать добавления поля типа контента, используя InheritanceManager из django-model-utils .

Затем, если вы вызовете .select_subclasses в наборе запросов, он снизит всеиз объектов, например:

FooPage.objects.select_subclasses().all()
0 голосов
/ 05 июля 2010

FooPage.objects.all() возвращает все объекты типа FooPage, эти объекты будут представлять собой смесь строк базовой таблицы базы данных для FooPage, FooBlog, FooGallery. Чтобы получить правильный URL, вы должны получить объект FooBlog или FooGallery, например

page.fooblog.get_absolute_url()

может выдать ошибку FooBlog.DoesNotExist, если страница - это просто объект страницы, т. Е. Созданный через FooPage, поэтому для получения правильных URL вы можете сделать что-то вроде этого

   urls = []
   for page in FooPage.objects.all():
        try:
            page = page.fooblog
        except FooBlog.DoesNotExist:
            pass

            urls.append(page.get_absolute_url())

в качестве альтернативы вы можете попытаться сделать FooPage абстрактным классом, если не хотите, чтобы FooPage была реальной таблицей.

...