Python项目 | Web应用程序之Django入门

Django入门

目标:使用 Django(http://djangoproject.com/ )开发一个名为“学习笔记”(LearningLog)的项目,这是一个在线日志系统,能够记录所学习的有关特定主题的知识。 并为这个项目制定规范,然后为应用程序使用的数据定义模型。使用Django的管理系统来输入一些初始数据,再学习编写视图和模板,让Django能够为我们 的网站创建网页。

Django是一个Web框架 ——一套用于帮助开发交互式网站的工具。Django能够响应网页请求,还能更轻松地读写数据库、管理用户等。

1、建立项目

【1】制定规范

制定的规范如下: 编写一个名为“学习笔记”的Web应用程序,让用户能够记录感兴趣的主题,并在学习每个主题的过程中添加日志条目。“学习笔记”的主页对这个网站进行描述, 并邀请用户注册或登录。用户登录后,就可创建新主题、添加新条目以及阅读既有的条目。 

【2】建立虚拟环境

要使用Django,首先需要建立一个虚拟工作环境。虚拟环境是系统的一个位置,可以在其中安装包,并将其与其他Python包隔离。

新建一个项目目录,并命名为learning_log。再在终端中切换到这个目录,并创建一个虚拟环境:python -m venv 11_env

这里运行了模块venv ,并使用它来创建一个名为ll_env的虚拟环境。

【3】激活虚拟环境

建立虚拟环境后,使用以下命令激活它:11_env\Scripts\activate

运行后:

要停止使用虚拟环境,可执行命令deactivate :

关闭了运行虚拟环境的终端,虚拟环境也将不再处于活动状态。

【4】安装Django

创建并激活虚拟环境后,就可安装Django:pip install Django

由于是在虚拟环境中工作,因此在所有的系统中,安装Django的命令都相同:不需要指定标志--user ,也无需使用python -m pip install package_name 这样较长的命令。 另外,Django仅在虚拟环境处于活动状态时才可用。

【5】在Django中创建项目

在处于活动的虚拟环境的情况下执行命令:django-admin.py startproject learning_log .(注意这里命令末尾有个句点,让新项目使用合适的目录结构,便于后期部署到服务器)

运行了命令dir(在Linux系统上应为ls),可看到Django新建了一个名为learning_log的目录。还创建了一个名为manage.py的文件,这是一个简单的程序,它接受 命令并将其交给Django的相关部分去运行。我们将使用这些命令来管理诸如使用数据库和运行服务器等任务。

 目录learning_log包含4个文件,其中最重要的是settings.py、urls.py和wsgi.py。

  • 文件settings.py指定Django如何与系统交互以及如何管理项目。在开发项目的过程中,将修改其中一些设置,并添加一些设置。
  • 文件urls.py告诉Django应创建哪些网页来响应浏览器请求。
  • 文件wsgi.py帮助Django提供它创建的文件,这个文件名是web server gateway interface(Web服务器网关接口 )的首字母缩写。

【6】创建数据库

执行命令:python manage.py  migrate

首次执行命令migrate 时,将让Django确保数据库与项目的当前状态匹配。在使用SQLite的新项目中首次执行这个 命令时,Django将新建一个数据库。

运行命令dir ,其输出表明Django又创建了一个文件——db.sqlite3。SQLite是一种使用单个文件的数据库,是编写简单应用程序的理想选择,因为它让你不用太关注数据库管理的问题。

【7】查看项目

执行命令:python manage.py runserver,核实Django是否正确地创建了项目:

Django启动一个服务器,能够查看系统中的项目,了解它们的工作情况。在浏览器中输入URL以请求网页时,该Django服务器将进行响应:生成合适的网页,并将其发送 给浏览器。

从信息中可看到:Django通过检查确认正确地创建了项目;并指出了使用的Django版本以及当前使用的设置文件的名称;它指出了项目的URL: http://127.0.0.1:8000/ 。

打开Web浏览器,并输入URL:http://localhost:8000/,或者请输入http://127.0.0.1:8000/。将看到类似于下图所示的页面,这个页面是Django创建的,让你知道到目前为止一切ok。若要关闭这个服务器,按Ctrl+ C即可。

 

2、创建应用程序

现在,前面打开的终端窗口中还运行着runserver 。再打开一个终端窗口,并切换到manage.py所在的目录。激活该虚拟环境,再执行命令startapp :

命令startapp appname 让Django建立创建应用程序所需的基础设施。查看项目目录,看到其中新增了一个文件夹learning_logs。打开这个文件夹查看,其中最重要的文件是models.py、admin.py和views.py。

【1】定义模型

使用models.py来定义要在应用程序中管理的数据。

在该项目中涉及的数据有:每位用户都需要在学习笔记中创建很多主题。用户输入的每个条目都与特定主题相关联,这些条目将以文本的方式显示。还需要存储每个条目的时间戳,以便能够告诉用户各个条目都是什么时候创建的。

打开文件models.py:

from django.db import models

# Create your models here.

已经导入了模块models,还让创建自己的模型。模型告诉Django如何处理应用程序中存储的数据。在代码层面,模型就是一个类,就像前面讨论的每个类一样,包含属性和方法。

下面是表示用户将要存储的主题的模型:

from django.db import models

# Create your models here.

class Topic(models.Model):
    # 用户学习的主题
    text = models.CharField(max_length=200)
    date_added = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        # 返回模型的字符串表示
        return self.text

创建了一个名为Topic 的类,它继承了Model :Django中一个定义了模型基本功能的类。Topic 类只有两个属性:text 和date_added 。

属性text是一个CharField:由字符或文本组成的数据。需要存储少量的文本,如名称、标题或城市时,可使用CharField 。定义CharField 属性时,必须告诉Django 该在数据库中预留多少空间。

属性date_added 是一个DateTimeField :记录日期和时间的数据。传递了实参auto_add_now=True ,每当用户创建新主题时,这都让Django将这个属性自动设置成当前日期和时间。

要获悉可在模型中使用的各种字段,参阅Django ModelField Reference(Django模型字段参考),其网址为https://docs.djangoproject.com/en/1.8/ref/models/fields/ 。 

需要告诉Django,默认应使用哪个属性来显示有关主题的信息。Django调用方法__str__() 来显示模型的简单表示。在这里,编写了方法__str__() ,它返回存储在属性text 中的字符串。

【2】激活模型

要使用模型,必须让Django将应用程序包含到项目中。为此,打开settings.py(它位于目录learning_log/learning_log中),将看到一个这样的片段,即告诉Django哪些应用程序安装在项目中:

# skip

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]
# skip

这是一个元组,告诉Django项目是由哪些应用程序组成的。

将INSTALLED_APPS 修改成下面这样,将前面的应用程序添加到这个元组中:


INSTALLED_APPS = [
    #skip

    'django.contrib.staticfiles',

    # 我的应用程序
    'learning_logs',
]

通过将应用程序编组,在项目不断增大,包含更多的应用程序时,有助于对应用程序进行跟踪。

接下来,需要让Django修改数据库,使其能够存储与模型Topic 相关的信息。为此,在终端窗口中执行下面的命令:python manage.py makemigrations learning_logs

命令makemigrations 让Django确定该如何修改数据库,使其能够存储与定义的新模型相关联的数据。输出表明Django创建了一个名为0001_initial.py的迁移文件,这个文件将在数据库中为模型Topic 创建一个表。

下面来应用这种迁移,让Django替我们修改数据库,执行命令:python manage.py migrate

Django确认为learning_logs 应用迁移时一切正常(OK )。

每当需要修改“学习笔记”管理的数据时,都采取如下三个步骤:修改models.py;对learning_logs 调用makemigrations ;让Django迁移项目。

【3】Django管理网站

为应用程序定义模型时,Django提供的管理网站(admin site)能够轻松地处理模型。网站的管理员可使用管理网站,但普通用户不能使用。在本节中,我们将建立管理网站, 并通过它使用模型Topic 来添加一些主题。

创建超级用户

Django允许创建具备所有权限的用户——超级用户。权限决定了用户可执行的操作。最严格的权限设置只允许用户阅读网站的公开信息;注册了的用户通常可阅读自己的私有 数据,还可查看一些只有会员才能查看的信息。为有效地管理Web应用程序,网站所有者通常需要访问网站存储的所有信息。

为在Django中创建超级用户,执行下面的命令并按提示做:python manage.py createsuperuser

向管理网站注册模型

Django自动在管理网站中添加了一些模型,如User 和Group ,但对于自己创建的模型,必须手工进行注册。

创建应用程序learning_logs 时,Django在models.py所在的目录中创建了一个名为admin.py的文件:

from django.contrib import admin

# Register your models here.

向管理网站注册Topic ,输入代码:

from django.contrib import admin
from learning_logs.models import Topic

admin.site.register(Topic)

导入注册的模型Topic ,再使用admin.site.register() 让Django通过管理网站管理自己的模型。

现在,使用超级用户账户访问管理网站:访问http://localhost:8000/admin/ ,并输入刚创建的超级用户的用户名和密码,将看到:

这个网页能够添加和修改用户和用户组,还可以管理与刚才定义的模型Topic 相关的数据。

添加主题:

向管理网站注册Topic 后,添加第一个主题。单击Topics进入主题网页,它几乎是空的,是因为还没有添加任何主题。单击Add,看到一个用于添加新主题的表单。在第一个方框中输入Chess ,再单击Save,这将返回到主题管理页面,其中包含刚创建的主题。 再创建一个主题,以便有更多的数据可供使用。再次单击Add,并创建另一个主题Rock Climbing 。当单击Save时,将重新回到主题管理页面,其中包含主题Chess和 Rock Climbing。

【4】定义模型Entry

要记录学到的国际象棋和攀岩知识,需要为用户可在学习笔记中添加的条目定义模型。每个条目都与特定主题相关联,这种关系被称为多对一关系,即多个条目可关联到同一个主题。

模型Entry 的代码:

from django.db import models

# Create your models here.

class Topic(models.Model):
    # skip

class Entry(models.Model):
    # 学到的有关某个主题的具体知识
    topic = models.ForeignKey(Topic, on_delete=models.CASCADE)
    text = models.TextField()
    date_added = models.DateTimeField(auto_now_add=True)

    class Meta:
        verbose_name_plural = 'entries'
    def __str__(self):
        # 返回模型的字符串表示
        return self.text[:50] + "..."

像Topic 一样,Entry 也继承了Django基类Model 。第一个属性topic 是一个ForeignKey 实例(在django2.0后,定义外键和一对一关系的时候需要加on_delete选项,此参数为了避免两个表里的数据不一致问题,不然会报错: TypeError: __init__() missing 1 required positional argument: 'on_delete')。外键是一个数据库术语,它引用了数据库中的另一条记 录;这些代码将每个条目关联到特定的主题。每个主题创建时,都给它分配了一个键(或ID)。需要在两项数据之间建立联系时,Django使用与每项信息相关联的键。稍后将根据这些联系获取与特定主题相关联的所有条目。

接下来是属性text ,它是一个TextField 实例。这种字段不需要长度限制。在Entry 类中嵌套了Meta 类。Meta 存储用于管理模型的额外信息,在这里,它能够设置一个特殊属性,让Django在需要时使用Entries 来表示多个条目。如果没有这个类, Django将使用Entrys来表示多个条目。最后,方法__str__() 告诉Django,呈现条目时应显示哪些信息。由于条目包含的文本可能很长,让Django只 显示text 的前50个字符,还添加了一个省略号,指出显示的并非整个条目。

【5】迁移模型Entry

由于添加了一个新模型,因此需要再次迁移数据库:修改models.py,执行命令python manage.py makemigrations app_name , 再执行命令python manage.py migrate 。

迁移数据库并查看输出:

生成了一个新的迁移文件:0002_entry.py,它告诉Django如何修改数据库,使其能够存储与模型Entry 相关的信息。执行命令migrate ,Django应用了这种迁移且一切顺利。

【6】向管理网站注册Entry

还需要注册模型Entry 。修改admin.py:

from django.contrib import admin
from learning_logs.models import Topic,Entry

admin.site.register(Topic)
admin.site.register(Entry)

返回到http://localhost/admin/ ,看到learning_logs下列出了Entries。单击Entries的Add链接,或者单击Entries再选择Add entry。将看到一个下拉列表,让你能够选择要为哪个主题创 建条目,还有一个用于输入条目的文本框。从下拉列表中选择Chess,并添加一个条目,点击Save。下面创建了两条国际象棋的条目和一条攀岩条目:

【7】Django shell

输入一些数据后,就可通过交互式终端会话以编程方式查看这些数据了。这种交互式环境称为Django shell,是测试项目和排除其故障的理想之地。下面是一个交互式shell会话示例:

在活动的虚拟环境中执行时,命令python manage.py shell 启动一个Python解释器,可使用它来探索存储在项目数据库中的数据。在这里,导入了模 块learning_logs.models 中的模型Topic ,然后使用方法Topic.objects.all() 来获取模型Topic 的所有实例;它返回的是一个列表,称为查询集 (queryset)。 可以像遍历列表一样遍历查询集。

下面演示了如何查看分配给每个主题对象的ID:

从输出可知,主题Chess的ID为1,而Rock Climbing的ID为2。注意print需要缩进。

知道对象的ID后,就可获取该对象并查看其任何属性。查看主题Chess的属性text 和date_added 的值:

还可以查看与主题相关联的条目。前面给模型Entry 定义了属性topic ,这是一个ForeignKey ,将条目与主题关联起来。利用这种关联,Django能够获取与特定主题相关联的所有条目:

为通过外键关系获取数据,可使用相关模型的小写名称、下划线和单词set。例如,假设你有模型Pizza 和Topping ,而Topping通过一个外键关联到Pizza ;如果你有 一个名为my_pizza 的对象,表示一张比萨,就可使用代码my_pizza.topping_set.all() 来获取这张比萨的所有配料。

编写用户可请求的网页时,我们将使用这种语法。确认代码能获取所需的数据时,shell很有帮助。如果代码在shell中的行为符合预期,那么它们在项目文件中也能正确地工作。如果代码引发了错误或获取的数据不符合预期,那么在简单的shell环境中排除故障要比在生成网页的文件中排除故障容易得多。我们不会太多地使用shell,但应继续使用它来熟悉对存储在项目中的数据进行访问的Django语法。 (注意每次修改模型后,你都需要重启shell,这样才能看到修改的效果。要退出shell会话,Windows系统按Ctr + Z,再按回车键)

3、创建网页:学习笔主页

使用Django创建网页的过程通常分三个阶段:定义URL、编写视图和编写模板。

首先,必须定义URL模式。URL模式描述了URL是如何设计的,让Django知道如何将浏览器请求与网站URL匹配,以确定返回哪个网页。 每个URL都被映射到特定的视图 ——视图函数获取并处理网页所需的数据。视图函数通常调用一个模板,后者生成浏览器能够理解的网页。

为明白其中的工作原理,创建学习笔记的主页。定义该主页的URL、编写其视图函数并创建一个简单的模板。 就目前,主页只显示标题和简单的描述。

【1】映射URL

用户通过在浏览器中输入URL以及单击链接来请求网页,因此需要确定项目需要哪些URL。主页的URL最重要,它是用户用来访问项目的基础URL。

当前,基础 URL(http://localhost:8000/)返回默认的Django网站,让我们知道正确地建立了项目。修改这一点,将这个基础URL映射到“学习笔记”的主页。打开项目主文件夹learning_log中的文件urls.py,包含learning_logs的URL::

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include(('learning_logs.urls', "learning_logs"),namespace="learning_logs")),
]

包含实参namespace ,能够将learning_logs 的URL同项目中的其他URL区分开来。另外包含了namespace参数必须知道app_name,这里是参数“learning_logs”

默认的urls.py包含在文件夹learning_log中,现在需要在文件夹learning_logs中创建另一个urls.py文件:


# 定义learning_log的URL模式

from django.conf.urls import url
from  . import views

urlpatterns = [
    # 主页
    url(r'^$', views.index ,name='index'),
    
]

导入了模块views ,其中的句点让Python从当前的urls.py模块所在的文件夹中导入视图。在这个模块中,变量urlpatterns 是一个列表,包含可在应用程 序learning_logs 中请求的网页。

实际的URL模式是一个对函数url() 的调用,这个函数接受三个实参。第一个是一个正则表达式。Django在urlpatterns 中查找与请求的URL字符串匹配的正则表达 式,因此正则表达式定义了Django可查找的模式。

正则表达式r'^$' 。其中的r 让Python将接下来的字符串视为原始字符串,而引号告诉Python正则表达式始于和终于何处。脱字符(^ )让Python查看字符串的开头, 而美元符号让Python查看字符串的末尾。总体而言,这个正则表达式让Python查找开头和末尾之间没有任何东西的URL。Python忽略项目的基础URL(http://localhost:8000/),因此这个正则表达式与基础URL匹配。其他URL都与这个正则表达式不匹配。如果请求的URL不与任何URL模式匹配,Django将返回一个错误页面。

url() 的第二个实参指定了要调用的视图函数。请求的URL与前述正则表达式匹配时,Django将调用views.index (这个视图函数将在下一节编写)。第三个实参将 这个URL模式的名称指定为index,让我们能够在代码的其他地方引用它。每当需要提供到这个主页的链接时,我们都将使用这个名称,而不编写URL。

【2】编写视图

视图函数接受请求中的信息,准备好生成网页所需的数据,再将这些数据发送给浏览器:这通常是使用定义了网页是什么样的模板实现的。

learning_logs中的文件views.py是执行命令python manage.py startapp 时自动生成的,当前内容只导入了函数render() ,它根据视图提供的数据渲染响应。为主页编写视图:

from django.shortcuts import render


def index(request):
    # 学习笔记主页
    return  render(request, 'learning_logs/index.html')

【3】编写模板

在文件夹learning_logs中新建一个文件夹,并将其命名为templates。在文件夹templates中,再新建一个文件夹,并将其命名为learning_logs。并在learning_logs中,新建一个文件,并将其命名为index.html,再在这个文件中编写如下代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <p>Learning Log</p>
    <p>Learning log helps you keep track of your learning ,for any topic you're learning about.</p>
</body>
</html>

请求这个项目的基础URL:http://localhost:8000/,将看到刚才创建的网页,而不是默认的Django网页。Django接受请求的URL,发现该URL与模式r'^$' 匹配,因此 调用函数views.index() ,这将使用index.html包含的模板来渲染网页:

4、创建其他网页

创建两个显示数据的网页,其中一个列出所有的主题,另一个显示特定主题的所有条目。对于每个网页,将指定URL模式,编写一个视图函数,并编写一个模板。这样做之前,先创建一个父模板,项目中的其他模板都将继承它。

【1】模板继承

创建网站时,几乎都有一些所有网页都将包含的元素。可编写一个包含通用元素的父模板,并让每个网页都继承这个模板,而不必在每个网页中重复定义这些通用元素。

父模板:

这个文件包含所有页面都有的元素;其他的模板都继承base.html。当前,所有页面都包含的元素只有顶端的标题。在每个页面中包含这个模板,将这个标题设置为到主页的链接:


<p>
    <a href="{%  url 'learning_logs:index' %}">Learning Log</a>
</p>

{%  block content %}{%  endblock content %}

为创建链接,使用了一个模板标签 ,它是用大括号和百分号({% %} )表示的。模板标签是一小段代码,生成要在网页中显示的信息。在这个实例中,模板标签{% url 'learning_logs:index' %} 生成一个URL,该URL与learning_logs/urls.py中定义的名 为index 的URL模式匹配。在这个示例中,learning_logs 是一个命名空间 ,而index 是该命名空间中一个名称独特的URL模式。

让模板标签来生成URL,可让链接保持最新容易得多。要修改项目中的URL,只需修改urls.py中的URL模式,这样网页被请求时,Django将自动插入修改后的URL。

在该项目中,每个网页都将继承base.html,从现在开始,每个网页都包含到主页的链接。插入的一对块标签中,块名为content ,是一个占位符,其中包含的信息将由子模板指定。 子模板并非必须定义父模板中的每个块,因此在父模板中,可使用任意多个块来预留空间,而子模板可根据需要定义相应数量的块。

子模板:

重新编写index.html,使其继承base.html:

{% extends "learning_logs/base.html" %}

{% block content %}
  <p>Learning Log helps you keep track of your learning, for any topic you're
learning about.
  </p>
{% endblock content %}

其中插入了一个名为content 的{% block %} 标签,以定义content 块。不是从父模板继承的内容都包含在content 块中,在这里是一个描述项目“学习笔记”的 段落。并使用标签{% endblock content %} 指出了内容定义的结束位置。

【2】显示所有主题的页面

现在需要做的是:显示全部主题的网页以及显示特定主题中条目的网页。所有主题页面显示用户创建的所有主题,它是第一个需要使用数据的网页。

URL模式:

先定义显示所有主题的页面的URL,修改learning_logs/urls.py:


# 定义learning_log的URL模式

from django.conf.urls import url
from  . import views

urlpatterns = [
    # 主页
    url(r'^$', views.index ,name='index'),

    # 显示所有主题的页面
    url(r'^topics/$', views.topics, name='topics')

]

视图:

函数topics() 需要从数据库中获取一些数据,并将其发送给模板。在views.py中添加的代码如下:

from django.shortcuts import render
from .models import Topic

def index(request):
    # skip

def topics(request):
    # 显示所有主题
    topics = Topic.objects.order_by('date_added')
    context = {'topics':topics}
    return render(request, 'learning_logs/topics.html',context)

函数topics() 包含一个形参:Django从服务器那里收到的request 对象,查询数据库:请求提 供Topic 对象,并按属性date_added 对它们进行排序,将返回的查询集存储在topics 中。 定义了一个将要发送给模板的上下文context。上下文是一个字典,其中的键是将在模板中用来访问数据的名称,而值是要发送给模板的数据。在这里,只有一个 键—值对,它包含在网页中显示的一组主题。创建使用数据的网页时,除对象request 和模板的路径外,我们还将变量context 传递给render() 。

模板:

显示所有主题的页面的模板接受字典context ,以便能够使用topics() 提供的数据。创建topics.html:


{% extends "learning_logs/base.html" %}
{% block content %}
<p>Topics</p>
    <ul> {% for topic in topics %}
        <li>{{ topic }}</li>
       {% empty %}
        <li>No topics have been added yet.</li>
            {% endfor %}
    </ul>
{% endblock content %}

模板中,每个for 循环都必须使用{% endfor %} 标签来显式地指出其结束位置。因此在模板中,循环类似于下面这样:

{% for item in list %}
do something with each item
{% endfor %}

要在模板中打印变量,需要将变量名用双花括号括起来。每次循环时,代码{{ topic }} 都被替换为topic 的当 前值。这些花括号不会出现在网页中,它们只是用于告诉Django我们使用了一个模板变量。

模板标签{% empty %} ,它告诉Django在列表topics 为空时该怎么办:这里是打印一条消息,告诉用户还没有添加任何主题。

修改父模板base.html,使其包含到显示所有主题的页面的链接:


<p>
    <a href="{%  url 'learning_logs:index' %}">Learning Log</a>-
    <a href="{% url 'learning_logs:topics' %}">Topics</a>
</p>

{%  block content %}{%  endblock content %}

刷新浏览器中的主页,将看到链接Topics。单击这个链接,将看到下图网页。

【3】显示特定主题的页面

创建一个专注于特定主题的页面:显示该主题的名称及该主题的所有条目。同样,定义一个新的URL模式,编写一个视图并创建一个模板。修改显示所有主题的网页,让每个项目列表项都是一个链接,单击它将显示相应主题的所有条目。

URL模式:

显示特定主题的页面的URL模式与前面的所有URL模式都稍有不同,因为它将使用主题的id 属性来指出请求的是哪个主题。例如,如果用户要查看主题Chess(其id 为1)的详细 页面,URL将为http://localhost:8000/topics/1/。下面是与这个URL匹配的模式,它包含在learning_logs/urls.py中:


# 定义learning_log的URL模式

from django.conf.urls import url
from  . import views

urlpatterns = [
    # skip

    # 特定主题的详细页面
    url(r'^topics/(?P<topic_id>\d+)/$', views.topic, name='topic'),

]

这个URL模式中的正则表达式——r'^topics/(?P\d+)/$' 。r 让Django将这个字符串视为原始字符串,并指出正则表达式包含在引号内。这个 表达式的第二部分(/(?P\d+)/ )与包含在两个斜杠内的整数匹配,并将这个整数存储在一个名为topic_id 的实参中。

这部分表达式两边的括号捕获URL中的值;?P 将匹配的值存储到topic_id 中;而表达式\d+ 与包含在两个斜杆内的任何数字都匹配,不管这个数字为多少位。 发现URL与这个模式匹配时,Django将调用视图函数topic() ,并将存储在topic_id 中的值作为实参传递给它。在这个函数中,使用topic_id 的值来获取相应的主题。

视图:

函数topic() 需要从数据库中获取指定的主题以及与之相关联的所有条目:

def topic(request, topic_id):
    # 显示单个主题及其所有的条目
    topic = Topic.objects.get(id=topic_id)
    entries = topic.entry_set.order_by('-date_added')
    context = {'topic':topic,'entries':entries}
    return  render(request, 'learning_logs/topic.html', context)

 这是第一个除request 对象外还包含另一个形参的视图函数。这个函数接受正则表达式(?P\d+) 捕获的值,并将其存储到topic_id 中。使用get() 来获取指定的主题,就像前面在Django shell中所做的那样。获取与该主题相关联的条目,并将它们按date_added 排序:date_added 前面的减号 指定按降序排列,即先显示最近的条目。我们将主题和条目都存储在字典context 中,再将这个字典发送给模板topic.html。 

模板:

模板需要显示主题的名称和条目的内容;如果当前主题不包含任何条目,我们还需向用户指出这一点:


{% extends 'learning_logs/base.html' %}
{% block content %}
    <p>Topic: {{ topic }}</p>
    <p>Entries:</p>
    <ul>
        {% for entry in entries %}
            <li>
                <p>{{ entry.date_added|date:'M d, Y H:i' }}</p>
                <p>{{ entry.text|linebreaks }}</p>
            </li>
        {% empty %}
            <li>
There are no entries for this topic yet.
            </li>
        {% endfor %}
    </ul>
{% endblock content %}

每个项目列表项都将列出两项信息:条目的时间戳和完整的文本。为列出时间戳,显示属性date_added 的值。在Django模板中,竖线(| )表示模板过滤器—— 对模板变量的值进行修改的函数。过滤器date: 'M d, Y H:i' 以这样的格式显示时间戳:January 1, 2015 23:00。接下来的一行显示text 的完整值,而不仅仅是entry 的前 50个字符。过滤器linebreaks 将包含换行符的长条目转换为浏览器能够理解的格式,以免显示为一个不间断的文本块。使用模板标签{% empty %} 打 印一条消息,告诉用户当前主题还没有条目。

显示所有主题的页面中每个主题都设置为链接:

在浏览器中查看显示特定主题的页面前,修改模板topics.html,让每个主题都链接到相应的网页,如下所示:


{% extends "learning_logs/base.html" %}
{% block content %}
<p>Topics</p>
    <ul> {% for topic in topics %}
        <li>
           <a href="{% url 'learning_logs:topic' topic.id %}">{{ topic }}</a>
        </li>
    {% empty %}
        <li>No topics have been added yet.</li>
            {% endfor %}
    </ul>
{% endblock content %}

刷新显示所有主题的页面,再单击其中的一个主题,看到:

5、小结

学习了:

  • 如何使用Django框架来创建Web应用程序。
  • 如何创建应用程序,以及如何定义表示应用程序数据的模型。
  • 创建使用数据库,以及在你修改模型后,Django可为你迁移数据库提供什么样的帮助。
  • 如何创建可访问管理网站的超级用户,并使用管理网站输入了一些初始数据。
  • 探索了Django shell,它让你能够在终端会话中处理项目的数据。
  • 如何定义URL、创建视图函数以及编写为网站创建网页的模板。
  • 使用了模板继承,它可简化各个模板的结构,并使得修改网站更容易。 

下一章:Python项目 | Web应用程序之用户账户

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值