English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
A view is a web 'type' in a Django application, providing specific functionality and having specific templates. For example, in a blog application, there may be the following views:
Blog home page - display the last few articles. Enter the 'detail' page - permanent link page for a single item. Archive page - display all entries for all months of a given year. Monthly archive page - display all items for all days of a given month. Daily archive page - display all entries for a specific day. Comment operation - handle publishing comments for a given input.
In our poll application, there are the following four views:
The 'index' page of the issue - display the last few issues. The 'detail' page of the issue - display the text of an issue without results but with a form to vote. The 'results' page of the issue - display the results of a specific issue. Voting operation - handle voting on a specific issue to make a specific choice.
In Django, web pages and other content are provided by views. Each view is represented by a simple Python function (or method, based on a class view). Django selects a view by examining the majority of the public's favored URL (more precisely, the part of the URL after the domain).
A URL pattern is a general form of a simple URL - for example: /newsarchive/<year>/<month>/.
Now, let's add some views in polls/views.py. These views are a bit different because they need a parameter:
def detail(request, question_id): return HttpResponse("You're looking at question %s." % question_id) def results(request, question_id): response = "Вы смотрите результаты вопроса %s." return HttpResponse(response % question_id) def vote(request, question_id): return HttpResponse("Вы голосуете за вопрос %s." % question_id)
Эти новые представления добавляются в модуль polls.urls в следующий вызов url(), код в файле polls/urls.py выглядит следующим образом:
from django.conf.urls import url from . import views urlpatterns = [ # Пример: /polls/ url(r'^$', views.index, name='index'), # Пример: /polls/5/ url(r'^(?P<question_id>[0-9]+)/$', views.detail, name='detail'), # Пример: /polls/5/results/ url(r'^(?P<question_id>[0-9]+)/results/$', views.results, name='results'), # Пример: /polls/5/vote/ url(r'^(?P<question_id>[0-9]+)/vote/$', views.vote, name='vote'), ]
Вы можете открыть «/polls/34/» в браузере. Это вызовет метод detail() и отобразит любое предоставленное содержимое URL. Попробуйте повторно访问 «/polls/34/results/» и «/polls/34/vote/» — это покажет временные результаты и страницу голосования.
include() легко включает плагины и адреса. Поскольку polls находится в своих собственных конфигурациях URL (polls/urls.py), они могут быть расположены в «/polls/», или «/fun_polls/», или «/content/polls/», или в корне любого другого пути, и приложение все еще будет работать.
Ниже показано, что происходит, если пользователь вводит «/polls/34/» в этой системе:
Django находит соответствие '^polls/' Затем Django удаляет соответствующий текст («polls/»)
Вместе с тем отправляется оставшийся текст «34/» в конфигурацию URL для polls.urls для дальнейшей обработки соответствия шаблону r'^(?P<question_id>[0-9]+)/$', чтобы вызвать функцию представления detail(), как показано ниже:
detail(request=<HttpRequest object>, question_id='34')
question_id='34' является частью (?P<question_id>[0-9]+), и вокруг этой модели используется окружающая скобка для «захвата» соответствующего текста, который затем передается в функцию представления; ?P<question_id> определяет имя, которое будет использоваться для распознавания соответствующей модели; а также [0-9]+ соответствует последовательности чисел (одному числу).
Поскольку шаблон URL является регулярным выражением, его можно использовать для выполнения некоторых операций, без каких-либо ограничений. И нет необходимости добавлять расширение .html –除非 вы этого хотите, в этом случае вы можете сделать это так:}}
url(r'^polls/latest\.html$', views.index),
Каждый вид отвечает за одно из двух действий: возвращает объект HttpResponse, содержащий запрошенный контент страницы, или выбрасывает исключение, такое как HTTP 404. Измените код файла polls/views.py следующим образом:
from django.http import HttpResponse from models import Question def index(request): latest_question_list = Question.objects.order_by('-pub_date')[:5] output = ', '.join([q.question_text for q in latest_question_list]) return HttpResponse(output) # Leave the rest of the views (detail, results, vote) unchanged
Здесь есть проблема: веб-дизайн硬编码 в представлении. Если вы хотите изменить вид страницы, вам нужно редактировать этот Python код. Поэтому давайте используем систему шаблонов Django, чтобы разделить код Python на шаблоны, которые можно использовать в представлениях. polls/templates/polls/index.html Введите следующий код:
{% if latest_question_list %} <ul> {% for question in latest_question_list %} <li><a href="/polls/{{ question.id }}/">{{ question.question_text }}</a></li> {% endfor %} </ul> {% else %} <p>No polls are available.</p> {% endif %}
Теперь我们来更新首页视图 polls/views.py 使用以下模板(代码):
from django.http import HttpResponse from django.template import loader from models import Question def index(request): latest_question_list = Question.objects.order_by('-pub_date')[:5] template = loader.get_template('polls/index.html') context = { 'latest_question_list': latest_question_list, } return HttpResponse(template.render(context, request))
Этот код загружает шаблон polls/index.html и передает ему контекст. Контекст является словарем, который отображает имена переменных шаблона на Python-объекты. Теперь откройте URL (http://127.0.0.1:8000/polls/) и посмотрите результат:
Это очень распространенный способ загрузки шаблона, заполнения контекста и рендеринга шаблона, который возвращает объект HttpResponse. Django предоставляет快捷 способ. Вот полный вид index() - перепишите polls/views.py следующим образом:
from django.shortcuts import render from models import Question def index(request): latest_question_list = Question.objects.order_by('-pub_date')[:5] context = {'latest_question_list': latest_question_list} return render(request, 'polls/index.html', context)
Обратите внимание, что после выполнения этой операции в различных видах нам больше не нужно импортировать загрузчики и объект HttpResponse (если вы хотите сохранить HttpResponse, если у вас все еще есть короткие методы detail, results и vote).
Теперь让我们解决这个问题 детального просмотра - страницы, отображающей текст вопроса опроса. Добавьте код вида (polls/views.py):
from django.http import Http404 from django.shortcuts import render from models import Question # ... def detail(request, question_id): try: question = Question.objects.get(pk=question_id) except Question.DoesNotExist: raise Http404("Вопрос не существует") return render(request, 'polls/detail.html', {'question': question})
Обратите внимание здесь: вид вызывает исключение HTTP404, если проблема с идентификатором запроса не существует.
Мы будем обсуждать, какие изменения можно сделать в polls/detail.html в будущем, но если нужно быстро использовать приведенный выше пример, файл polls/templates/polls/detail.html должен содержать только:
{{question}}
Взвлечь 404-ошибку, теперь мы запросили несуществующий вопрос, например: http://127.0.0.1:8000/polls/100/, результат отображается следующим образом:
Очень распространенный способ использования get() и вызова HTTP404-ошибки. Django предоставляет краткий способ. Вот как был изменен вид detail() в polls/views.py:
from django.shortcuts import get_object_or_404, render from models import Question # ... def detail(request, question_id): question = get_object_or_404(Question, pk=question_id) return render(request, 'polls/detail.html', {'question': question})
Функция get_object_or_404() принимает в качестве первого параметра Django-модель и количество произвольных параметров с ключевыми словами, которые передаются в функцию get() управления моделью.
Если объект не существует, вызывается HTTP404.
Существует также функция get_list_or_404(), которая работает аналогично get_object_or_404() – только вместо метода get() используется метод filter(). Если список пуст, он вызывает HTTP404.
Вернемся к нашему приложению polls и функции detail(). Из-за проблемы контекста переменных шаблон polls/detail.html выглядит следующим образом:
<h1>{{ question.question_text }}</h1> <ul> {% for choice in question.choice_set.all %} <li>{{ choice.choice_text }}</li> {% endfor %} </ul>
Система шаблонов использует синтаксис точечной проверки для доступа к свойствам переменных. В этом примере {{question.question_text }}, первый Django действительно ищет в словаре объекта question. Если не найдено, он пытается выполнить поиск свойств – если поиск свойств не удался, он пытается выполнить поиск по индексу списка.
Теперь проверьте написанный нами код, откройте его в браузере: http://127.0.0.1:8000/polls/5/, и получите результат:
Помните, когда мы создаем ссылку на вопрос в polls/index.html, часть, которая硬кодирована, выглядит так:
<li><a href="/polls/{{question.id}}/">{{question.question_text}}</a></li>
Проблема с этим методом, основанным на硬кодировании, заключается в том, что он требует изменения URL в множестве шаблонов. Однако, так как в модуле polls.urls определен параметр url() для имени URL, вы можете удалить зависимость от конкретного URL-пути в конфигурации URL, используя шаблонный тег {% url %}:
<li><a href="{etail'question.id%}">{{question.question_text}}</a></li>
Этот способ работает за счет определения URL-имени для поиска в модуле polls.urls. Вы можете точно увидеть, как определено имя URL 'detail':
... # the 'name' value as called by the {% url %} template tag url(r'^(?P<question_id>[0-9]+)/$', views.detail, name='detail'), ...
Если вы хотите изменить URL-адрес детального вида голосования на другой, например polls/specifics/12/, в шаблонах (или templates), вам нужно изменить его в polls/urls.py:
... # added the word 'specifics' url(r'^specifics/(?P<question_id>[0-9]+)/$', views.detail, name='detail'), ...
Этот учебный проект содержит только одно приложение - polls. В реальном проекте Django может быть от пяти до двух десятков и более приложений. Как Django различает их URL-адреса? Например, приложение для голосования имеет детальный вид, поэтому в одном проекте может быть то же приложение, что и в блоге. Как использовать шаблонный тег {% url %}, чтобы сообщить Django, какие приложения имеют такой вид?
Ответ заключается в добавлении пространства имен к URLconf. В файле polls/urls.py продолжайте движение, добавьте имя приложения и настройте пространство имен приложения, откройте файл polls/urls.py:
from django.conf.urls import url from . import views app_name = 'polls' urlpatterns = [ url(r'^$', views.index, name='index'), url(r'^(?P<question_id>[0-9]+)/$', views.detail, name='detail'), url(r'^(?P<question_id>[0-9]+)/results/$', views.results, name='results'), url(r'^(?P<question_id>[0-9]+)/vote/$', views.vote, name='vote'), ]
Теперь измените шаблон polls/index.html, откройте файл polls/templates/polls/index.html и добавьте следующий код:
<li><a href="{etail'question.id%}">{{question.question_text}}</a></li>
Сделайте это, чтобы он указывал на пространство имён detail вид, откройте файл polls/templates/polls/index.html следующим образом:
<li><a href="{olls:detail'question.id%}">{{question.question_text}}</a></li>