Django Tutorial Part 5: Creating our home page
先决条件: | 阅读 Django简介。 完成上一篇教程主题(包括 Django教程第4部分:Django管理网站)。 |
---|---|
目的: | 了解如何创建简单的URL映射和视图(在URL中没有编码数据),以及如何从模型获取数据和创建模板。 |
概述
现在我们已经定义了我们的模型并创建了一些初始的库记录来处理,现在是编写代码以向用户呈现信息的时候了。 我们需要做的第一件事是确定我们希望在我们的页面中显示哪些信息,然后定义返回这些资源的适当的URL。 然后,我们需要创建url映射器,视图和模板来显示这些页面。
下面的图提供了处理HTTP请求/响应时需要实现的数据和事物的主要流程的提示。 由于我们已经创建了模型,我们需要创建的主要内容是:
- URL maps to forward the supported URLs (and any information encoded in the URLs) to the appropriate view functions.
- View functions to get the requested data from the models, create an HTML page displaying the data, and return it to the user to view in the browser.
- Templates used by the views to render the data.
正如你将在下一节中看到的,我们将有5个页面来显示,这在一篇文章中是很有用的。 因此,本文的大部分内容将集中在展示如何实现主页(我们将转到后续文章中的其他页面)。 这应该让您对URL映射器,视图和模型在实践中如何工作有良好的端到端理解。
定义资源URL
由于此版本的LocalLibrary 对于最终用户而言基本上是只读的,因此我们只需为网站(首页)和显示列表的网页提供着陆页 和书和作者的详细视图。
我们需要为我们的网页的网址是:
-
catalog/
— The home/index page. -
catalog/books/
— The list of all books. -
catalog/authors/
— The list of all authors. -
catalog/book/<id>
— The detail view for the specific book with a field primary key of<id>
(the default). So for example,/catalog/book/3
, for the third book added. -
catalog/author/<id>
— The detail view for the specific author with a primary key field named<id>.
So for example,/catalog/author/11
, for the 11th author added.
前三个URL用于列出索引,书籍和作者。 这些不会编码任何附加信息,并且尽管返回的结果将取决于数据库中的内容,运行以获取信息的查询将始终相同。
相反,最后两个URL用于显示关于特定书或作者的详细信息 - 这些URL编码要在URL中显示的项的标识(示为 < id>
代码>)。 URL映射器可以提取编码信息并将其传递给视图,然后它将动态确定从数据库获取什么信息。 通过在我们的URL中编码信息,我们只需要一个url映射,视图和模板来处理每本书(或作者)。
注意:Django允许您以任何方式构建网址 - 您可以按上面所示对网址正文中的信息进行编码,或使用URL GET
参数(例如 > / book /?id = 6
)。 无论您使用哪种方法,网址都应保持干净,逻辑和可读(此处查看W3C建议 / a>)。
Django文档倾向于在URL的正文中推荐编码信息,这是他们认为鼓励更好的URL设计的做法。
如概述中所讨论的,本文的其余部分描述如何构建索引页。
创建索引页
我们将创建的第一个页面是索引页面( catalog /
)。 这将显示一些静态HTML,以及数据库中不同记录的一些计算的"计数"。 为了完成这项工作,我们必须创建一个URL映射,视图和模板。
注意:在本节中值得特别注意。 一些材料是所有页面的共同。
URL映射
当我们创建骨架网站时,我们为目录应用程序创建了一个基本的 /catalog/urls.py 文件。 目录应用程序URL包含在映射 catalog /
的项目中,因此获取到此映射器的URL必须以 catalog /
开头 在正斜杠之后的URL中的所有字符串)。
打开 urls.py ,然后粘贴下面粗体显示的行。
urlpatterns = [ url(r'^$', views.index, name='index'), ]
这个 url()
函数定义了一个URL模式( r\'^ $\'
)和一个视图函数,如果检测到模式 index - views.py 中名为 index()
的函数。 网址格式是 Python正则表达式(RE)。 我们将在本教程中进一步讨论RE,但对于这种情况,所有你需要知道的是,^ $的RE将模式匹配空字符串(^是字符串开始标记,$是结束 的字符串标记)。
注意:匹配的网址实际上是 catalog /
+< empty string> (因为我们在目录应用程序中,假定为 / catalog /
)。 如果我们收到一个URL为 / catalog /
的HTTP请求,我们的第一个视图函数将被调用。
此 url()
函数还指定了 name
参数,该参数唯一标识了此特定的URL映射。 您可以使用此名称"反转"映射器 - 动态创建指向映射器设计处理的资源的URL。 例如,现在我们可以通过在我们的模板中创建以下链接来链接到我们的主页:
<a href="{% url 'index' %}">Home</a>.
注意:我们当然可以对上述链接进行硬编码(例如< a href =" / catalog / "> Home< / a>
>),但是如果我们改变主页的模式(例如到 / catalog / index
),模板将不再正确链接。 使用反向url映射是更加灵活和健壮!
视图(基于功能)
视图是一种处理HTTP请求,根据需要从数据库获取数据,通过使用HTML模板呈现此数据来生成HTML页面,然后在HTTP响应中返回HTML以向用户显示的功能。 索引视图遵循此模型 - 它获取有关多少 Book
, BookInstance
,可用的 BookInstance
和 Author
记录 我们在数据库中,并将它们传递到模板进行显示。
打开 catalog / views.py ,并注意该文件已导入 shortcuts.render"class ="external"> render()快捷方式函数,使用模板和数据生成HTML文件。
from django.shortcuts import render # Create your views here.
复制文件底部的以下代码。 第一行导入我们将在所有视图中访问的模型类。
from .models import Book, Author, BookInstance, Genre def index(request): """ View function for home page of site. """ # Generate counts of some of the main objects num_books=Book.objects.all().count() num_instances=BookInstance.objects.all().count() # Available books (status = 'a') num_instances_available=BookInstance.objects.filter(status__exact='a').count() num_authors=Author.objects.count() # The 'all()' is implied by default. # Render the HTML template index.html with the data in the context variable return render( request, 'index.html', context={'num_books':num_books,'num_instances':num_instances,'num_instances_available':num_instances_available,'num_authors':num_authors}, )
视图函数的第一部分使用模型类上的 objects.all()
属性获取记录计数。 它还获取一个状态字段值为\'a\'(可用)的 BookInstance
对象的列表。 您可以在上一篇教程中了解有关如何从模型访问的更多信息( Django教程第3部分:使用模型>搜索记录) )。
在函数结束时,我们调用 render()
函数创建并返回一个HTML页面作为响应(这个快捷函数包装了许多其他函数,简化了这个常见的用例)。 这采用原始的 request
对象(一个 HttpRequest
),一个具有数据占位符的HTML模板和一个 context
包含将插入到这些占位符中的数据的字典)。
我们将在下一节中更多地讨论模板和上下文变量; 让我们创建我们的模板,这样我们可以向用户显示一些东西!
模板
模板是定义文件(例如HTML页面)的结构或布局的文本文件,具有用于表示实际内容的占位符。 Django会自动在应用程序中名为"模板"的目录中查找模板。 因此,例如,在我们刚才添加的索引视图中, render()
函数将期望能够找到 / locallibrary / catalog / templates / 127.0.0.1:8000
现在将提供一个相当直观的错误消息"TemplateDoesNotExist at / catalog /", 。
注意:根据项目的设置文件,Django会查看多个模板的位置(在已安装的应用程序中搜索是默认设置!)。 您可以在模板中找到更多关于Django如何查找模板及其支持的模板格式的信息。 a>(Django docs)。
Extending templates
注意:根据项目的设置文件,Django会查看多个模板的位置(在已安装的应用程序中搜索是默认设置!)。 您可以在模板中找到更多关于Django如何查找模板及其支持的模板格式的信息。 a>(Django docs)。...
例如,基本模板 base_generic.html 可能类似于以下文本。 如您所见,这包含一些"常见的"HTML和标题,边栏和使用命名的 block
和 endblock
模板标签(以粗体显示)标记的内容的部分。 块可以为空,或包含将为"派生页"默认使用的内容。
注意:模板标签就像可以在模板中使用的函数,用于循环遍历列表,基于变量的值执行条件操作等。除了模板 标记模板语法允许您引用模板变量(从视图传递到模板中),并使用重新格式化变量(例如,将字符串设置为小写)的模板过滤器。
<!DOCTYPE html> <html lang="en"> <head> {% block title %}<title>Local Library</title>{% endblock %} </head> <body> {% block sidebar %}<!-- insert default navigation text for every page -->{% endblock %} {% block content %}<!-- default content text (typically empty) -->{% endblock %} </body> </html>
当我们想为特定视图定义一个模板时,我们首先指定基本模板(使用 extend
模板标签 - 参见下一个代码清单)。 如果在模板中有要替换的任何部分,我们使用与基本模板中使用的相同的 block
/ endblock
部分声明这些部分。
例如,下面的代码片段显示了我们如何使用 extends
模板标记,并覆盖 content
块。 最终生成的HTML将包含基本模板中定义的所有HTML和结构(包括您在 title
块中定义的默认内容),但使用新的内容
块插入代替detault一。
{% extends "base_generic.html" %} {% block content %} <h1>Local Library Home</h1> <p>Welcome to <em>LocalLibrary</em>, a very basic Django website developed as a tutorial example on the Mozilla Developer Network.</p> {% endblock %}
The LocalLibrary base template
我们计划用于 LocalLibrary 网站的基本模板如下所示。 如您所见,这包含了 title
, sidebar
和 content
的一些HTML和定义的块。 我们有一个默认标题(我们可能想要更改)和一个默认边栏,其中包含所有图书和作者的列表链接(我们可能不想更改,但我们允许范围这样做,如果需要, 在块中)。
注意:我们还引入了两个其他模板标签: url
和 load static
。 这些将在以下各节中讨论。
创建新文件 - / locallibrary / catalog / templates / base_generic.html - 并提供以下内容:
<!DOCTYPE html> <html lang="en"> <head> {% block title %}<title>Local Library</title>{% endblock %} <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script> <!-- Add additional CSS in static file --> {% load static %} <link rel="stylesheet" href="{% static 'css/styles.css' %}"> </head> <body> <div class="container-fluid"> <div class="row"> <div class="col-sm-2"> {% block sidebar %} <ul class="sidebar-nav"> <li><a href="{% url 'index' %}">Home</a></li> <li><a href="">All books</a></li> <li><a href="">All authors</a></li> </ul> {% endblock %} </div> <div class="col-sm-10 "> {% block content %}{% endblock %} </div> </div> </div> </body> </html>
该模板使用(并包括)来自 Bootstrap 的JavaScript和CSS,以改进HTML页面的布局和显示方式。 使用Bootstrap或另一个客户端web框架是一个快速的方法来创建一个有吸引力的网页,可以扩大在不同的浏览器大小,它也允许我们处理页面演示,而无需进入任何细节 - 我们只是 想在这里聚焦于服务器端代码!
基本模板还引用了一个提供一些额外样式的本地css文件( styles.css )。 创建 /locallibrary/catalog/static/css/styles.css 并提供以下内容:
.sidebar-nav { margin-top: 20px; padding: 0; list-style: none; }
The index template
创建HTML文件 / locallibrary / catalog / templates / index.html ,并为其提供如下所示的内容。 您可以看到,我们在第一行中扩展了我们的基本模板,然后将默认的 content
块替换为此模板的新模块。
{% extends "base_generic.html" %} {% block content %} <h1>Local Library Home</h1> <p>Welcome to <em>LocalLibrary</em>, a very basic Django website developed as a tutorial example on the Mozilla Developer Network.</p> <h2>Dynamic content</h2> <p>The library has the following record counts:</p> <ul> <li><strong>Books:</strong> {{ num_books }}</li> <li><strong>Copies:</strong> {{ num_instances }}</li> <li><strong>Copies available:</strong> {{ num_instances_available }}</li> <li><strong>Authors:</strong> {{ num_authors }}</li> </ul> {% endblock %}
在动态内容部分中,我们为视图中包含的信息声明了占位符(模板变量)。 变量使用"双括号"或"句柄"语法标记(参见上面的粗体部分)。
注意:您可以轻松地识别是否要使用模板变量或模板标签(函数),因为变量具有双括号( {{num_books}}
),而代码 ( {%extends"base_generic.html"%}
)的单个大括号中。
这里需要注意的是,这些变量是用我们传递给 context
字典的键命名的。 (见下文); 当呈现模板时,这些将被其相关联的值替换。
return render( request, 'index.html', context={'num_books':num_books,'num_instances':num_instances,'num_instances_available':num_instances_available,'num_authors':num_authors}, )
Referencing static files in templates
您的项目可能使用静态资源,包括JavaScript,CSS和图像。 由于这些文件的位置可能未知(或可能会更改),因此Django允许您在模板中相对于 STATIC_URL
全局设置指定这些文件的位置(默认框架网站设置值 STATIC_URL
改为\' / static /
\',但您可以选择在内容传送网络或其他地方托管这些内容。
在模板中,您首先调用l oad
模板标签,指定"static"以添加此模板库(如下所示)。 加载静态后,您可以使用 static
模板标记,指定相关文件的相对URL。
<!-- Add additional CSS in static file --> {% load static %} <link rel="stylesheet" href="{% static 'css/styles.css' %}">
如果需要,可以以相同的方式在页面中添加图像。 例如:
{% load static %} <img src="{% static 'catalog/images/local_library_model_uml.png' %}" style="width:555px;height:540px;"/>
注意:上面的更改指定了文件的位置,但Django不会默认提供这些文件。 虽然当我们创建网站骨架时,我们已启用全球网址映射程序( /locallibrary/locallibrary/urls.py )中的开发网络服务器 ,您仍然需要安排他们在生产中服务。 我们稍后会看这个。
有关使用静态文件的详细信息,请参阅管理静态文件(Django docs)。
Linking to URLs
上面的基本模板引入了 url
模板标记。
<li><a href="{% url 'index' %}">Home</a></li>
此标记采用 urls.py 中调用的 url()
函数的名称,以及关联视图从该函数接收的任何参数的值,并返回一个网址 您可以使用链接到资源。
它是什么样子的?
在这一点上,我们应该创建显示索引页所需的一切。 运行服务器( python3 manage.py runserver
),然后打开浏览器 http://127.0。 0.1:8000 / 。 如果一切设置正确,您的网站应该看起来像下面的屏幕截图。
; width:874px;">
注意:您将无法使用所有图书和所有作者链接,因为这些链接的网址,视图和模板 网页尚未定义(目前我们只是在 base_generic.html
模板中为这些链接插入了占位符)。
挑战自己
这里有几个任务来测试你对模型查询,视图和模板的熟悉程度。
- Declare a new title block in the index template and change the page title to match this particular page.
- Modify the view to generate a count of genres and a count of books that contain a particular word (case insensitive) and then add these fields to the template.
概要
我们现在已经为我们的网站创建了一个主页 - 一个HTML页面,其中显示了数据库中的一些记录数量,并且链接到我们的其他待创建页面。 一路上,我们学到了很多关于URL映射器,视图,使用我们的模型查询数据库,如何从视图传递信息到模板以及如何创建和扩展模板的基本信息。
在下一篇文章中,我们将基于我们的知识创建其他四个页面。
也可以看看
- Writing your first Django app, part 3: Views and Templates (Django docs)
- URL dispatcher (Django docs)
- View functions (DJango docs)
- Templates (Django docs)
- Managing static files (Django docs)
- Django shortcut functions (Django docs)