# Модели рубрик --- ## Над и подрубрики ---- Базовой модели, в которой будут храниться и надрубрики, и подрубрики, мы дадим имя Rubric. Ее структура приведена в таблице ![](https://i.imgur.com/alAbLS4.png) ---- Код класса модели Rubric. Не забываем, что код всех моделей заносится в модуль models.ру пакета приложения. ``` class Rubric (models.Model) : name = models.CharField(max_length=20, db_index=True, unique=True, verbose_name='Название') order = models.SmallIntegerField(default=0, db_index=True, verbose_name='Порядок') super_rubric = models.ForeignKey('SuperRubric', on_delete=models.PROTECT, null=True, blank=True, verbose_name='Надрубрика') ``` ---- Для работы С надрубриками объявим прокси-модель SuperRubric, производную от Rubric. Она будет обрабатывать только надрубрики. ---- Код обоих классов: И модели SuperRubric, И диспетчера записей SuperRubricManager ``` class SuperRubricManager(models.Manager): def get_queryset(self): return super().get_queryset().filter(super_rubric__isnull=True) class SuperRubric(Rubric): objects = SuperRubricManager() def __str__(self) : return self.name class Meta: proxy = True ordering = ('order', 'name') verbose_name = 'Надрубрика' verbose_name_plural = 'Надрубрики' ``` ---- Условия фильтрации записей указываем в переопределенном методе get_queryset() Класса Диспетчера записей SuperRubricManager. В самом классе модели SuperRubric задаем диспетчер записей SuperRubricManager в качестве основного. ---- Код классов модели subRubric и диспетчера записей SubRubricManager ``` class SubRubricManager(models.Manager): def get_queryset(self): return super().get_queryset().filter(super_rubric__isnull=False) class SubRubric(Rubric): objects = SubRubricManager() def __str__(self) : return '%s - %s' % (self.super_rubric.name, self.name) class Meta: proxy = True ordering = ('super_rubric__order', 'super_rubric__name', 'order', 'name') verbose_name = 'Подрубрика' verbose_name_plural = 'Подрубрики' ``` ---- Диспетчер записей SubRubricManager будет отбирать лишь записи с непустым полем super_rubric (т.е. подрубрики). ---- Код классов редактора SuperRubricAdmin и встроенного редактора SubRubricinline. Не забываем, что код редакторов, равно как и код, регистрирующий модели и редакторы в подсистеме административного сайта, должен записываться в модуль admin.ру пакета приложения. ``` from .models import SuperRubric, SubRubric class SubRubricinline(admin.TabularInline): model = SubRubric class SuperRubricAdmin (admin.ModelAdmin) : exclude = ('super_rubric',) inlines = (SubRubricinline,) admin.site.register(SuperRubric, SuperRubricAdmin) ``` ---- У подрубрик сделаем поле надрубрики (super rubric) обязательным для заполнения. Для этого мы объявим форму SubRubricForm в модуле forms.py пакета приложения. ``` from .models import SuperRubric, SubRubric class SubRubricForm (forms.ModelForm): super_rubric = forms.ModelChoiceField(queryset=SuperRubric.objects.all(),empty_label=None, label='Надрубрика', required=True) class Meta: model = SubRubric fields = '__all__' ``` ---- Мы убрали у раскрывающегося списка, с помощью которого пользователь будет выбирать подрубрику, "пустой" пункт, присвоив параметру empty_label конструктора класса поля ModelChoiceField значение None. ---- Код, объявляющий класс редактора SubRubricAdmin. ``` from .forms import SubRubricForm class SubRubricAdmin(admin.ModelAdmin) : form = SubRubricForm admin.site.register(SubRubric, SubRubricAdmin) ``` --- ## Шаблон и контекстный процессор ---- Создадим в пакете приложения модуль middlewares.py и запишем в него код обработчика контекста bboard_context_processor() ``` from .models import SubRubric def bboard_context_processor(request): context = {} context['rubrics'] = SubRubric.objects.all() return context ``` ---- Откроем модуль settings.py пакета конфигурации и зарегистрируем только что написанный обработчик контекста. ``` TEMPLATES = [ { 'BACKEND': 'django.template.backends.dj ango.DjangoTemplates', 'OPTIONS': { 'context_processors': [ ... 'main.middlewares.bboard_context_processor', ], }, }, ] ``` ---- Выполним еще пару подготовительных действий. Во-первых, в модуле views.py пакета приложения объявим "пустой" контроллер-функцию by_rubric(): ``` def by_rubric(request, pk): pass ``` ---- Во-вторых, добавим в список маршрутов уровня приложения маршрут, ведущий на этот контроллер: ``` from .views import by_rubric ... urlpatterns = [ ... path('<int:pk>/', by_rubric, name='by_rubric'), path('<str:page>/', other_page, name='other'), ... ] ``` ---- Откроем шаблон layout\basic.html и исправим код вертикальной панели навигации следующим образом: ``` <a class="nav-link root" href="{% url 'main:index' %}">Главная</a> {% for rubric in rubrics %} {% ifchanged rubric.super_rubric.pk %} <span class="nav-link root font-weight-bold">{{ rubric.super_rubric.name }}</span> {% endifchanged %} <a class="nav-link" href="{% url 'main:by_rubric' pk=rubric.pk %}">{{ rubric.name }}</a> {% endfor %} <a class="nav-link root" href="{% url 'main:other' page='about' %}">О сайте</a> ```
{"metaMigratedAt":"2023-06-16T15:45:19.414Z","metaMigratedFrom":"Content","title":"Модели рубрик","breaks":true,"contributors":"[{\"id\":\"0d39d5a3-691d-488c-8f1e-1a0fb0be4f13\",\"add\":5489,\"del\":32}]"}
    246 views