Добавил правильные хлебные крошки
This commit is contained in:
parent
c65be53032
commit
61c7af35c1
@ -1,4 +1,4 @@
|
||||
from programmer.mixins import MenuContextMixin
|
||||
from programmer.mixins import MenuContextMixin, BreadcrumbMixin
|
||||
from django.views.generic import ListView, DetailView, CreateView
|
||||
from django.urls import reverse_lazy
|
||||
from django.contrib import messages
|
||||
@ -15,13 +15,22 @@ from django.shortcuts import redirect
|
||||
from django.contrib.admin.views.decorators import staff_member_required
|
||||
|
||||
|
||||
class ArticleListView(MenuContextMixin, ListView):
|
||||
class ArticleListView(MenuContextMixin, BreadcrumbMixin, ListView):
|
||||
"""Список статей"""
|
||||
model = Article
|
||||
template_name = 'blog/article_list.html'
|
||||
context_object_name = 'articles'
|
||||
paginate_by = 10
|
||||
|
||||
def get_breadcrumbs(self):
|
||||
if 'category_slug' in self.kwargs:
|
||||
category = Category.objects.get(slug=self.kwargs['category_slug'])
|
||||
return [
|
||||
{'title': 'Статьи', 'url_name': 'blog:article_list'},
|
||||
{'title': category.name, 'url_name': None},
|
||||
]
|
||||
return [{'title': 'Статьи', 'url_name': None}]
|
||||
|
||||
def get_queryset(self):
|
||||
category_slug = self.kwargs.get('category_slug')
|
||||
return get_published_articles(category_slug)
|
||||
@ -51,13 +60,26 @@ class ArticleListView(MenuContextMixin, ListView):
|
||||
return super().dispatch(*args, **kwargs)
|
||||
|
||||
|
||||
class ArticleDetailView(MenuContextMixin, DetailView, CreateView):
|
||||
class ArticleDetailView(MenuContextMixin, BreadcrumbMixin, DetailView, CreateView):
|
||||
"""Детальная страница статьи + форма комментария"""
|
||||
model = Article
|
||||
template_name = 'blog/article_detail.html'
|
||||
context_object_name = 'article'
|
||||
form_class = CommentForm
|
||||
|
||||
def get_breadcrumbs(self):
|
||||
article = self.get_object()
|
||||
return [
|
||||
{'title': 'Статьи', 'url_name': 'blog:article_list'},
|
||||
{
|
||||
'title': article.category.name,
|
||||
'url_name': 'blog:category_detail',
|
||||
'category_slug': article.category.slug,
|
||||
# 'url_args': [article.category.slug]
|
||||
},
|
||||
{'title': article.title, 'url_name': None},
|
||||
]
|
||||
|
||||
def get_object(self, queryset=None):
|
||||
article = get_article_by_slug(self.kwargs['slug'])
|
||||
if article is None:
|
||||
@ -110,7 +132,7 @@ class ArticleDetailView(MenuContextMixin, DetailView, CreateView):
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context.update({
|
||||
'title': "Статии | Инструкции",
|
||||
'title': "Статьи | Инструкции",
|
||||
'meta_description': (
|
||||
"Инструкции по работе в 1С и бизнес-решения"
|
||||
"инструкции, статьи помощь 1С."
|
||||
|
||||
@ -48,3 +48,26 @@ class MenuContextMixin(ContextMixin):
|
||||
return context
|
||||
|
||||
|
||||
class BreadcrumbMixin(ContextMixin):
|
||||
"""
|
||||
Миксин для добавления хлебных крошек в контекст.
|
||||
В дочерних классах нужно определить метод get_breadcrumbs().
|
||||
"""
|
||||
breadcrumbs = None
|
||||
|
||||
def get_breadcrumbs(self):
|
||||
"""
|
||||
Должен возвращать список словарей:
|
||||
[{'title': 'Название', 'url_name': 'url_name', 'url_args': [...], 'url_kwargs': {...}}, ...]
|
||||
Последний элемент без url_name (текущая страница).
|
||||
"""
|
||||
if self.breadcrumbs is not None:
|
||||
return self.breadcrumbs
|
||||
return []
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context['breadcrumbs'] = self.get_breadcrumbs()
|
||||
return context
|
||||
|
||||
|
||||
|
||||
@ -566,10 +566,26 @@
|
||||
<section class="content">
|
||||
<!-- Breadcrumbs -->
|
||||
{% block breadcrumbs %}
|
||||
<nav class="breadcrumbs">
|
||||
<nav class="breadcrumbs" aria-label="breadcrumb">
|
||||
<a href="{% url 'home' %}" class="breadcrumb-link">Главная</a>
|
||||
{% for crumb in breadcrumbs %}
|
||||
<span class="breadcrumb-separator">/</span>
|
||||
{% if crumb.url_name %}
|
||||
{% if crumb.category_slug %}
|
||||
<a href="{% url crumb.url_name category_slug=crumb.category_slug %}" class="breadcrumb-link">{{ crumb.title }}</a>
|
||||
{% elif crumb.url_args %}
|
||||
<a href="{% url crumb.url_name crumb.url_kwargs %}" class="breadcrumb-link">{{ crumb.title }}</a>
|
||||
{% else %}
|
||||
<a href="{% url crumb.url_name %}" class="breadcrumb-link">{{ crumb.title }}</a>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<span class="breadcrumb-current">{{ crumb.title }}</span>
|
||||
{% endif %}
|
||||
{% empty %}
|
||||
{# Если крошек нет, показываем просто заголовок страницы #}
|
||||
<span class="breadcrumb-separator">/</span>
|
||||
<span class="breadcrumb-current">{{ title }}</span>
|
||||
{% endfor %}
|
||||
</nav>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
@ -17,7 +17,7 @@ from django.db.models import Count, QuerySet
|
||||
from django.contrib.auth.decorators import login_required, user_passes_test
|
||||
from django.views.decorators.http import require_GET, require_POST
|
||||
from django.views.generic import TemplateView, ListView, CreateView, UpdateView
|
||||
from .mixins import PageViewTrackingMixin, MenuContextMixin
|
||||
from .mixins import PageViewTrackingMixin, MenuContextMixin, BreadcrumbMixin
|
||||
from .services import get_published_queryset, track_page_view
|
||||
from typing import Any, Dict, Type
|
||||
from django.template.loader import render_to_string
|
||||
@ -95,10 +95,13 @@ class HomePageView(BasePageView):
|
||||
return context
|
||||
|
||||
|
||||
class AboutPageView(BasePageView):
|
||||
class AboutPageView(BasePageView, BreadcrumbMixin):
|
||||
"""Страница 'О себе'."""
|
||||
template_name = 'programmer/about.html'
|
||||
|
||||
def get_breadcrumbs(self):
|
||||
return [{'title': 'Обо мне', 'url_name': None}]
|
||||
|
||||
def get_context_data(self, **kwargs: Any) -> Dict[str, Any]:
|
||||
context = super().get_context_data(**kwargs)
|
||||
|
||||
@ -116,7 +119,7 @@ class AboutPageView(BasePageView):
|
||||
return context
|
||||
|
||||
|
||||
class SolutionListView(BaseListView):
|
||||
class SolutionListView(BaseListView, BreadcrumbMixin):
|
||||
"""Список проектов с пагинацией."""
|
||||
model = Solution
|
||||
template_name = 'programmer/solution.html'
|
||||
@ -125,6 +128,9 @@ class SolutionListView(BaseListView):
|
||||
cards_template = 'programmer/includes/project_cards.html'
|
||||
ordering = ['-time_create']
|
||||
|
||||
def get_breadcrumbs(self):
|
||||
return [{'title': 'Проекты', 'url_name': None}]
|
||||
|
||||
def get_queryset(self) -> QuerySet:
|
||||
"""Возвращает только опубликованные проекты."""
|
||||
return get_published_queryset(self.model, order_by='-time_create')
|
||||
@ -146,7 +152,7 @@ class SolutionListView(BaseListView):
|
||||
return context
|
||||
|
||||
|
||||
class RecallListView(BaseListView):
|
||||
class RecallListView(BaseListView, BreadcrumbMixin):
|
||||
"""Список отзывов с пагинацией."""
|
||||
model = Recall
|
||||
template_name = 'programmer/recall.html'
|
||||
@ -154,6 +160,9 @@ class RecallListView(BaseListView):
|
||||
paginate_by = 5
|
||||
ordering = ['-time_create']
|
||||
|
||||
def get_breadcrumbs(self):
|
||||
return [{'title': 'Отзывы', 'url_name': None}]
|
||||
|
||||
def get_queryset(self) -> QuerySet:
|
||||
"""Возвращает только опубликованные отзывы."""
|
||||
return get_published_queryset(self.model, order_by='-time_create')
|
||||
@ -175,17 +184,23 @@ class RecallListView(BaseListView):
|
||||
return context
|
||||
|
||||
|
||||
class ProfileView(LoginRequiredMixin, PageViewTrackingMixin, MenuContextMixin, TemplateView):
|
||||
class ProfileView(LoginRequiredMixin, PageViewTrackingMixin, MenuContextMixin, BreadcrumbMixin, TemplateView):
|
||||
template_name = 'programmer/profile.html'
|
||||
|
||||
def get_breadcrumbs(self):
|
||||
return [{'title': 'Профиль', 'url_name': None}]
|
||||
|
||||
class RegisterView(PageViewTrackingMixin, MenuContextMixin, SuccessMessageMixin, CreateView):
|
||||
|
||||
class RegisterView(PageViewTrackingMixin, MenuContextMixin, SuccessMessageMixin, BreadcrumbMixin, CreateView):
|
||||
"""Регистрация нового пользователя"""
|
||||
template_name = 'programmer/register.html'
|
||||
form_class = RegistrationForm
|
||||
# success_url = reverse_lazy('profile')
|
||||
success_message = '✅ Регистрация успешна!'
|
||||
|
||||
def get_breadcrumbs(self):
|
||||
return [{'title': 'Регистрация', 'url_name': None}]
|
||||
|
||||
def get_success_url(self):
|
||||
# Если есть параметр next, используем его
|
||||
next_url = self.request.POST.get('next') or self.request.GET.get('next')
|
||||
@ -207,12 +222,18 @@ class RegisterView(PageViewTrackingMixin, MenuContextMixin, SuccessMessageMixin,
|
||||
return context
|
||||
|
||||
|
||||
class ProfileEditView(LoginRequiredMixin, PageViewTrackingMixin, MenuContextMixin, UpdateView):
|
||||
class ProfileEditView(LoginRequiredMixin, PageViewTrackingMixin, MenuContextMixin, BreadcrumbMixin, UpdateView):
|
||||
model = Profile
|
||||
form_class = ProfileForm
|
||||
template_name = 'programmer/profile_edit.html'
|
||||
success_url = reverse_lazy('profile')
|
||||
|
||||
def get_breadcrumbs(self):
|
||||
return [
|
||||
{'title': 'Профиль', 'url_name': 'profile'},
|
||||
{'title': 'Редактирование', 'url_name': None},
|
||||
]
|
||||
|
||||
def get_object(self, queryset=None):
|
||||
# Возвращаем профиль текущего пользователя
|
||||
return self.request.user.profile
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user