Как вы реализуете меню в сайте на Django?

Стоит задача сделать меню сайта максимально гибко и просто настраиваемым. В идеале - максимально приблизиться к управлению меню в Drupal, где ноды можно цеплять в меню сразу из интерфейса их редактирования.
Для этого сделан базовый класс Page, от которого наследуются все закрепляемые в меню страницы
class Page(models.Model):
    title = models.CharField(verbose_name="название", max_length=50)
    text = RichTextField(verbose_name="содержимое страницы")
    slug = AutoSlugField(populate_from='title', editable=True)
    objects = InheritanceManager()

    def __str__(self):
        return self.title

    def get_absolute_url(self):
        from django.core.urlresolvers import reverse
        return reverse('app.views.page_details', args=[str(self.slug)])

    class Meta:
        verbose_name = "страница"
        verbose_name_plural = "страницы"


само меню состоит из элементов MenuItem, от которого могут быть наследованы более специфичные, например PageMenuItem
class MenuItem(models.Model):
    title = models.CharField(verbose_name="название", max_length=50)
    description = models.CharField(verbose_name="описание", max_length=100, null=True, blank=True)
    weight = models.PositiveSmallIntegerField(verbose_name="вес", default=0)
    parent = models.ForeignKey('MenuItem', verbose_name="родительский пункт", null=True, blank=True)
    objects = InheritanceManager()

    def __str__(self):
        return self.title

    def url(self):
        return "#"

    def as_dict(self):
        return dict(
            id=self.id,
            title=self.title,
            description=self.description,
            weight=self.weight,
            url=self.url()
        )

    def children(self):
        menu_objects = MenuItem.objects.filter(parent=self).select_subclasses()
        menu_list = list()
        for menu_item in menu_objects:
            item = menu_item.as_dict()
            item['items'] = menu_item.children()
            menu_list.append(item)
        return menu_list

    class Meta:
        verbose_name = "пункт меню"
        verbose_name_plural = "пункт меню"
        ordering = ['weight']


class PageMenuItem(MenuItem):
    page = models.OneToOneField(Page, verbose_name="страница")

    def url(self):
        page = Page.objects.get_subclass(id=self.page_id)
        return page.get_absolute_url()


Вроде всё хорошо, но встал вопрос -- как можно добавить пункты меню, ведущие на страницы -- списки объектов? В голове крутятся синглтоны, для которых можно было бы просто указать признак активности, вес, и выводимое название с описанием, но с ними в django напряжёнка -- django_solo делает их с фиксированными id=1, что неприменимо в случае с наследованием.
Есть ли какие-то более красивые варианты?
  • Вопрос задан
  • 1829 просмотров
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы