Представления
В директории приложения questions открываем views.py и приводим к следующему виду:
from django.shortcuts import render, get_object_or_404, redirect
from django.conf import settings
from core.utils import pagination
from . import forms
from .models import Question
def index_view(request):
questions = pagination(request, Question.public.all(), settings.QUESTIONS_PER_PAGE)
if request.user.is_authenticated:
form = forms.QuestionForm(request.POST or None)
if form.is_valid():
form.save(request.user, request.META['REMOTE_ADDR'])
return redirect('questions:index')
else:
form = None
return render(request, 'questions/index.html', {
'questions': questions,
'form': form,
})
def question_view(request, slug, pk):
question = get_object_or_404(Question.public, pk=pk)
if question.slug != slug:
# делаем постоянный редирект, слаг был изменен
return redirect(question, permanent=True)
if request.user.is_authenticated:
form = forms.ArticleForm(request.POST or None)
if form.is_valid():
form.save(question, request.user, request.META['REMOTE_ADDR'])
return redirect(question)
else:
form = None
return render(request, 'questions/question.html', {
'question': question,
'form': form,
})
В первом представлении мы для начала разбиваем список вопросов на страницы и получаем нужную страницу в зависимости от номера в запросе соответственно.
Далее если пользователь авторизирован мы отображаем или проверяем и сохраняем форму создания нового вопроса, и в случае успеха перенаправляем на список вопросов.
Второе представление отображает тему конкретного вопроса и ответов к нему.
Механизм с проверкой слага аналогичен, как и в приложении Статьи. Но здесь стоит выделить следующую фишку — возможность создания коротких ссылок, которая не была описана в статьях.
Если необходимо дать короткую ссылку на ветку вопроса или статью мы можем заменить слаг на менее емкий текст.
Например, вот так выглядит обычная ссылка на вопрос:
/questions/obychnyi-zagolovok-tipovogo-voprosa-kotoryi-mozhet-zainteresovat-avtora-resursa-17/
Далее рассмотрим пример короткой ссылки:
/questions/q-17/
Здесь мы просто заменили содержимое слага буквой q. Но, благодаря разработанной нами системы предотвращения недоступности материала в случае если заголовок был изменен — нас перенаправит на действующую ссылку.
Затем в представлении если пользователь авторизирован показываем или проверяем и в случае успеха сохраняем форму добавления ответа.
Лента последних вопросов
В каталоге приложения создаем файл feeds.py:
from django.contrib.syndication.views import Feed
from django.utils.feedgenerator import Atom1Feed
from django.urls import reverse_lazy
from django.conf import settings
from .models import Question
class LatestQuestionsFeed(Feed):
feed_type = Atom1Feed
title = settings.SITE_TITLE
link = reverse_lazy('questions:index')
subtitle = 'Вопросы'
def items(self):
return Question.public.all()[:settings.QUESTIONS_ITEMS_IN_FEED]
def item_title(self, item):
return item.title
def item_description(self, item):
return item.summary
def item_pubdate(self, item):
return item.created
def item_updateddate(self, item):
return item.updated
Лента составлена аналогично, как и в приложении Статьи.
Карта вопросов
В директории приложения создаем файл sitemaps.py:
from django.contrib.sitemaps import GenericSitemap
from .models import Question
questions_sitemaps = {
'questions': GenericSitemap({
'queryset': Question.public,
'date_field': 'updated',
}, priority=0.7, changefreq=None),
}
Приоритет выставляем 0.7 поскольку вопросы являются второстепенным контентом.
Маршруты
В каталоге приложения создаем файл urls.py:
from django.conf.urls import url
from . import views
from .feeds import LatestQuestionsFeed
app_name = 'questions'
urlpatterns = [
url(r'^$', views.index_view, name='index'),
url(r'^feed/$', LatestQuestionsFeed(), name='feed'),
url(r'^(?P<slug>[\w-]+)-(?P<pk>\d+)/$', views.question_view, name='question'),
]
В директории проекта переходим в каталог zero, затем открываем urls.py и приводим к следующему виду:
from django.conf.urls import url, include
from django.contrib import admin
from django.views.generic.base import RedirectView
from django.contrib.sitemaps.views import sitemap
from django.conf.urls.static import static
from django.conf import settings
from questions.sitemaps import questions_sitemaps
from articles.sitemaps import articles_sitemaps
sitemaps = {}
sitemaps.update(questions_sitemaps)
sitemaps.update(articles_sitemaps)
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^ckeditor/', include('ckeditor_uploader.urls')),
url(r'^accounts/', include('accounts.urls')),
url(r'^questions/', include('questions.urls')),
url(r'^articles/', include('articles.urls')),
url(r'^$', RedirectView.as_view(pattern_name='articles:index'), name='index'),
url(r'^sitemap\.xml$', sitemap, {'sitemaps': sitemaps}, name='sitemap'),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
# Django Debug Toolbar
if settings.DEBUG:
import debug_toolbar
urlpatterns += [
url(r'^__debug__/', include(debug_toolbar.urls)),
]
Здесь мы добавляем карту вопросов и само приложение questions.