Динамическое меню из базы данных в 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 %}
Думаю, этого должно быть достаточно для простого одноуровневого меню.