В части 4 мы создали роут, по которому стали доступен список последних двух опросов. В этой части мы сделаем детальное отображение опроса.
1. Добавим роут в файл polls/urls.py:
Это значит, что представление PollDetailView будет вызываться, когда пользователь переходит, к примеру, по адресу: http://127.0.0.1:8000/polls/1
2. Создадим представление в файле polls/views.py:
Здесь мы создали класс представления, который расширяет встроенный в django класс DetailView, содержащий нужный функционал для отображения детальной страницы.
3. Детальное представление опроса должно быть формой с радиокнопками, чтобы ответ пользователя можно было отправить на определенный url, при обращению к которому будет вызвано представление, где данные запишутся в БД. Создадим такой шаблон по адресу polls/templates/polls/detail.html:
Обратите внимание на выражение: question.answer_set.all
Вот таким образом в шаблоне можно получить список всех элементов связанной таблицы. В нашем случае у каждого Вопроса есть несколько Ответов. При помощи приведенного выражения мы можем по экземпляру вопроса получить список соответствующих ему ответов.
Перейдем по адресу http://127.0.0.1:8000/polls/1/ и увидим результат:
4. Однако приведенная форма пока не работает.Чтобы она заработала, нужно добавить роут и представление для обработки POST-данных отправляемой формы. Создадим новый роут в файле polls/urls.py:
5. Создадим представление, но уже не в виде класса, а в виде функции. Отредактируем файл polls/views.py:
Здесь мы проверяем наличие переменной answer в POST-запросе. Если она есть, мы по коду ответа достаем запись из базы данных и увеличиваем счетчик votes на 1. После этого делаем редирект на страницу результатов (пока еще не создали).
6. Добавим новый роут страницы результатов опроса в polls/urls.py:
7. Для созданного роута создадим представление в polls/views.py:
8. Для созданного представления создадим шаблон polls/templates/polls/results.html:
Здесь мы при помощи фильтра Django dictsortreversed:"votes" сортируем ответы в порядке убывания числа голосов.
Выражение {% url 'polls:detail' question.id %} позволяет сформировать ссылку на детальную страницу просмотра опроса, где находится форма голосования. Здесь polls - неймспейс, указанный при подключении роутов приложения polls в главном файле роутов проекта firstsite/urls.py:
9. Проверим работу, перейдя в опрос: http://127.0.0.1:8000/polls/1/
Там мы увидим форму голосования. После выбора варианта ответа и нажатия "Голосовать" мы будем перенаправлены на страницу результатов опроса:
Продолжение - Опрос (ч.6)
1. Добавим роут в файл polls/urls.py:
# ... urlpatterns = patterns('', # ... url(r'^(?P\d+)/$', PollDetailView.as_view(), name='detail'), )
Это значит, что представление PollDetailView будет вызываться, когда пользователь переходит, к примеру, по адресу: http://127.0.0.1:8000/polls/1
2. Создадим представление в файле polls/views.py:
# -*- coding: utf-8 -*- from django.shortcuts import render from django.views.generic import ListView, DetailView from .models import Question, Answer # ... class QuestionDetailView(DetailView): model = Question template_name = 'polls/detail.html'
Здесь мы создали класс представления, который расширяет встроенный в django класс DetailView, содержащий нужный функционал для отображения детальной страницы.
3. Детальное представление опроса должно быть формой с радиокнопками, чтобы ответ пользователя можно было отправить на определенный url, при обращению к которому будет вызвано представление, где данные запишутся в БД. Создадим такой шаблон по адресу polls/templates/polls/detail.html:
<h1>{{ question.title }}</h1> {% if error_message %} <p><strong>{{ error_message }}</strong></p> {% endif %} <form action="" method="post"> {% csrf_token %} {% for answer in question.answer_set.all %} <input type="radio" name="answer" id="answer{{ forloop.counter }}" value="{{ answer.id }}" /> <label for="answer{{ forloop.counter }}">{{ answer.answer }}</label><br /> {% endfor %} <input type="submit" value="Голосовать" /> </form>
Обратите внимание на выражение: question.answer_set.all
Вот таким образом в шаблоне можно получить список всех элементов связанной таблицы. В нашем случае у каждого Вопроса есть несколько Ответов. При помощи приведенного выражения мы можем по экземпляру вопроса получить список соответствующих ему ответов.
Перейдем по адресу http://127.0.0.1:8000/polls/1/ и увидим результат:
4. Однако приведенная форма пока не работает.Чтобы она заработала, нужно добавить роут и представление для обработки POST-данных отправляемой формы. Создадим новый роут в файле polls/urls.py:
urlpatterns = patterns('', # ... url(r'^(?P\d+)/vote/$', vote, name='vote'), )
5. Создадим представление, но уже не в виде класса, а в виде функции. Отредактируем файл polls/views.py:
from django.shortcuts import render, get_object_or_404 from django.http import HttpResponseRedirect from django.core.urlresolvers import reverse from django.views.generic import ListView, DetailView from .models import Question, Answer # ... def vote(request, poll_id): question = get_object_or_404(Question, pk=poll_id) if request.POST.get('answer'): selected_answer = question.answer_set.get(pk=request.POST['answer']) selected_answer.votes += 1 selected_answer.save() return HttpResponseRedirect(reverse('polls:results', args=(question.id,))) else: return render(request, 'polls/detail.html', { 'question': question, 'error_message': "Вы не выбрали ответ.", })
Здесь мы проверяем наличие переменной answer в POST-запросе. Если она есть, мы по коду ответа достаем запись из базы данных и увеличиваем счетчик votes на 1. После этого делаем редирект на страницу результатов (пока еще не создали).
6. Добавим новый роут страницы результатов опроса в polls/urls.py:
urlpatterns = patterns('', # ... url(r'^(?P\d+)/results/$', ResultsView.as_view(), name='results'), )
7. Для созданного роута создадим представление в polls/views.py:
# ... class ResultsView(DetailView): model = Question template_name = 'polls/results.html'
8. Для созданного представления создадим шаблон polls/templates/polls/results.html:
<h1>{{ question.title }}</h1> <ul> {% for answer in question.answer_set.all|dictsortreversed:"votes" %} <li>{{ answer.answer }} - голосов: {{ answer.votes }}</li> {% endfor %} </ul> <a href="{% url 'polls:detail' question.id %}">Голосовать еще раз</a>
Здесь мы при помощи фильтра Django dictsortreversed:"votes" сортируем ответы в порядке убывания числа голосов.
Выражение {% url 'polls:detail' question.id %} позволяет сформировать ссылку на детальную страницу просмотра опроса, где находится форма голосования. Здесь polls - неймспейс, указанный при подключении роутов приложения polls в главном файле роутов проекта firstsite/urls.py:
urlpatterns = patterns('', # ... # Задаем неймспейс "polls" для импортируемых роутов приложения url(r'^polls/', include('polls.urls', namespace="polls")), )
9. Проверим работу, перейдя в опрос: http://127.0.0.1:8000/polls/1/
Там мы увидим форму голосования. После выбора варианта ответа и нажатия "Голосовать" мы будем перенаправлены на страницу результатов опроса:
Обратите внимание: ответы отсортированы в порядке убывания голосов.
Продолжение - Опрос (ч.6)
Комментариев нет:
Отправить комментарий