Динамическое меню из базы данных в Django

Я хочу хранить свои навигационные ссылки из стандартного навигационного меню в своей базе данных. В идеале это позволило бы некоторым конкретным (нетехническим) пользователям иметь возможность поддерживать ссылки на webapp. Сегодня мое навигационное меню является "статической" страницей, включенной в мой base.html и одинаково на всех обслуживаемых страницах. Любые изменения требуют от меня ручного обновления статического файла nav и повторного развертывания.

Моя проблема (и это может быть мой ограниченный опыт django) заключается в том, как иметь возможность генерировать данные и отображать их из base.html/nav include без необходимости буквально генерировать пункты меню при каждом рендеринге страницы (например, получать список меню и отправлять во все вызовы рендеринга). У меня десятки страниц, поэтому вручную это делать не реально.

Я искал это, и похоже, что я не единственный, но самое близкое решение датируется примерно 2006 годом, и я уверен, что за последние 15 лет в этой области произошли значительные изменения.

Буду признателен за любую информацию, которая может направить меня в правильном направлении. Будьте здоровы!

Если ваше меню - это просто список пунктов, вы можете создать одну таблицу базы данных, которая будет содержать как минимум ссылку текст, адрес, is_active и порядок, в котором они должны выравниваться. Таким образом, вам нужно получить navitems в каждом представлении, или вы можете сделать одно базовое представление, которое имеет переопределенный метод get_context_data.

Ваш код будет выглядеть следующим образом.

models.py

class NavLinks(models.Model):
    title = ...
    address = ...
    order = ...
    is_active = ...

    class Meta:
        ordering = ["order"]

views.py

from django.views.generic.base import ContextMixin

class NavView(ContextMixin):
    def get_context_data(self, *args,**kwargs):
            context = super().get_context_data(*args, **kwargs)
            context["nav_links"] = NavLinks.objects.filter(is_active=True)
            return context

Вы можете наследовать это представление в других представлениях, поэтому вам не нужно писать контекстную часть в каждом представлении, например

from django.views.generic import TemplateView

class IndexView(NavView, TemplateView):
    template_name = "index.html"

    # other methods and stuffs
    def get_context_data(self, *args,**kwargs):
        context =  super().get_context_data(*args, **kwargs)
        # this context has nav_links
        # other context data
        context["other"] = somedata
        return context

Теперь остается только показать данные в шаблоне, поэтому я бы создал один файл nav.html и расширил его в файле base.html

nav.html

<nav>
    <ul>
        {% for nav_link in nav_links %}
            <li><a href="{{nav_link.address}}">{{nav_link.title}}</a></li>
        {% endfor %}
    </ul>
</nav>

base.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    {% extends 'nav.html' %}
    {% block content %}
    {% endblock content %}
</body>
</html>

index.html

{% extends 'base.html' %}
{% block content %}
 <!-- Other Main Content -->
{% endblock content %}

Думаю, этого должно быть достаточно для простого одноуровневого меню.

Вернуться на верх