99 lines
3.8 KiB
Python
99 lines
3.8 KiB
Python
from programmer.mixins import MenuContextMixin
|
|
from django.views.generic import ListView, DetailView, CreateView
|
|
from django.urls import reverse_lazy
|
|
from django.contrib import messages
|
|
from django.utils.decorators import method_decorator
|
|
from django.views.decorators.cache import cache_page
|
|
from .models import Article, Category
|
|
from .services import (
|
|
get_published_articles, get_article_by_slug,
|
|
increment_article_views, add_comment_to_article
|
|
)
|
|
from .forms import CommentForm
|
|
from django.http import Http404
|
|
from django.shortcuts import redirect
|
|
from django.contrib.admin.views.decorators import staff_member_required
|
|
|
|
|
|
class ArticleListView(MenuContextMixin, ListView):
|
|
"""Список статей"""
|
|
model = Article
|
|
template_name = 'blog/article_list.html'
|
|
context_object_name = 'articles'
|
|
paginate_by = 10
|
|
|
|
def get_queryset(self):
|
|
category_slug = self.kwargs.get('category_slug')
|
|
return get_published_articles(category_slug)
|
|
|
|
def get_context_data(self, **kwargs):
|
|
context = super().get_context_data(**kwargs)
|
|
context['categories'] = Category.objects.all()
|
|
if 'category_slug' in self.kwargs:
|
|
context['current_category'] = Category.objects.filter(
|
|
slug=self.kwargs['category_slug']
|
|
).first()
|
|
return context
|
|
|
|
@method_decorator(cache_page(60 * 5)) # кэширование страницы на 5 минут
|
|
def dispatch(self, *args, **kwargs):
|
|
return super().dispatch(*args, **kwargs)
|
|
|
|
|
|
class ArticleDetailView(MenuContextMixin, DetailView, CreateView):
|
|
"""Детальная страница статьи + форма комментария"""
|
|
model = Article
|
|
template_name = 'blog/article_detail.html'
|
|
context_object_name = 'article'
|
|
form_class = CommentForm
|
|
|
|
def get_object(self, queryset=None):
|
|
article = get_article_by_slug(self.kwargs['slug'])
|
|
if article is None:
|
|
raise Http404("Статья не найдена")
|
|
return article
|
|
|
|
def get(self, request, *args, **kwargs):
|
|
# Увеличиваем счётчик просмотров при GET запросе
|
|
self.object = self.get_object()
|
|
increment_article_views(self.object)
|
|
return super().get(request, *args, **kwargs)
|
|
|
|
def post(self, request, *args, **kwargs):
|
|
self.object = self.get_object()
|
|
form = self.get_form()
|
|
if form.is_valid():
|
|
return self.form_valid(form)
|
|
else:
|
|
return self.form_invalid(form)
|
|
|
|
def get_initial(self):
|
|
"""Возвращает пустые начальные данные для формы комментария."""
|
|
initial = super().get_initial()
|
|
initial['content'] = ''
|
|
return initial
|
|
|
|
def form_valid(self, form):
|
|
comment = add_comment_to_article(
|
|
article=self.object,
|
|
data=form.cleaned_data
|
|
)
|
|
messages.success(self.request, "Ваш комментарий отправлен на модерацию.")
|
|
return redirect(self.object.get_absolute_url())
|
|
|
|
def get_context_data(self, **kwargs):
|
|
context = super().get_context_data(**kwargs)
|
|
# Добавляем только одобренные комментарии
|
|
context['moderated_comments'] = self.object.comments.filter(is_moderated=True)
|
|
return context
|
|
|
|
|
|
@method_decorator(staff_member_required, name='dispatch')
|
|
class ArticleDraftPreviewView(DetailView):
|
|
model = Article
|
|
template_name = 'blog/article_detail.html' # используем тот же шаблон
|
|
context_object_name = 'article'
|
|
|
|
def get_queryset(self):
|
|
# Для предпросмотра показываем даже неопубликованные статьи
|
|
return Article.objects.all() # без фильтрации по is_published |