Django入门——《Python编程从入门到实践》
Django是一个Web框架——一套用于帮助开发交互式网站的工具。Django能够响应网页请求,还能让你更轻松地读写数据库、管理用户等。
1、建立项目
开始编写一个名为“学习笔记”的Web应用程序,让用户能够记录感兴趣的主题,并在学习每个主题的过程中添加日志条目。“学习笔记”的主页对这个网站进行描述,并邀请用户注册或登录。用户登录后,就可以创建主题、添加新条目以及阅读既有的条目。
1.安装Python:Python
2.安装IDE(我使用的是Pycharm社区版):Pycharm
3.在Pycharm新建项目:
File->New Project,设置如下
4.安装Django:Django
cmd
进入终端,cd到python安装的Script文件夹下,利用pip命令安装Django,或将python安装目录Script文件夹路径加入环境变量中,则可直接使用pip命令。- 使用
pip install django
命令安装Django
5.在Django中创建项目:
在Pycharm中新建的项目中,利用Terminal终端在虚拟环境下使用django-admin startproject project-name .
创建项目,注意命令后的点号,书上提到,忘记点号在部署应用程序时会遇到一些配置问题。忘记点号,就将创建的目录文件夹删除再运行一边命令
Django在项目中新建了一个名为learnning_log的目录,其中最重要的是settings.py、urls,py、wsgi.py
- 文件settings.py指定Django如何与你的系统交互以及如何管理项目。在开发过程中我们将修改其中过一些设置,并添加一些设置
- 文件urls.py告诉Django应创建哪些网页来响应浏览器请求
- 文件wsgi.py帮助Django提供它创建的文件,这个文件名是web server gateway interface(Web服务器网关接口)的首字母缩写
还创建了一个名为manage.py的文件,这是一个简单的程序,它接受命令并将其交给Django的相关部分去运行。我们将使用这些命令来管理诸如使用数据库和运行服务器等任务
6.创建数据库:
使用migrate
命令创建一个供Django使用的数据库:python manage.py migrate
我们将修改数据库称为迁移数据库。首次执行命令migrate时,将让Django确保数据库与项目的当前状态匹配。在使用SQLite的新项目中首次执行这个命令时,Django将创建一个数据库
运行过命令后,我们会发现,项目中多出来了一个db.sqlite3文件,SQLite是一种使用单个文件的数据库,是编写简单应用程序的理想选择,因为它让你不用太关注数据库管理的问题
7.查看项目
执行命令runserver,合适Django是否正确地创建了项目:python manage.py runserver
Django启动一个服务器,让你能够查看系统中地项目,了解他们地工作。当浏览器中输入url请求网页时,该Django服务器将进行响应:生成合适地网页,并将其发送给浏览器
注意 如果出现错误消息 “That portis already iin use"(指定端口已被占用),请执行
python manage.py runserver 8001
,让Django使用另一个端口;如果这个端口也不可用,请不断执行上述命令,更改其中指定的端口号,直到找到可用的端口。
2、创建应用程序
Django项目由一系列应用程序组成,它们协同工作,让项目成为一个整体。我接下来创建一个应用程序,他将完成项目的大部分工作。
当前,在前面打开的终端窗口运行着runserver
。我们再打开一个终端窗口,执行命令startapp
命令startapp appname让Django建立创建应用程序的基础设施。现在查看项目目录,新增了一个文件夹learning_logs
该文件夹中最重要的文件是models.py、admin.py、views.py
接下来使用models.py来定义我们在应用程序中管理的数据
1.定义模型:
我们考虑设计的数据。每位用户在学习笔记中需要创建很多主题。用户输入每个条目都与特定主题相关联,这些条目以文本的形式显示。我们还需要存储每个条目的时间戳,以便能够告诉用户各个条目都是什么时候创建的
打开models.py,它为我们导入了模块models,我们还能创建自己的模型。模型告诉Django如何处理应用程序中存储的数据。现在我们创建一个名为Topic的类,继承Model,表示用户将存储的主题的模型,它包含text和date_added两个属性
- 属性text是一个CharField——由字符或文本组成的数据,我们还设置max_length=200告诉Django在数据库中主题名应预留多少空间
- 属性date_added是一个DateTimeField——记录日期和时间的数据,我们传递auto_now_add=True,当用户创建新主题时,让Django将该属性设置成当前日期和时间
- 我们还需要告诉Django,默认使用哪个属性显示有关主题的信息。注意:在python2.7中,应调用__ unicode __ ()方法而不是__ str __ ()方法
2.激活模型:
要使用模型,必须让Django将应用程序包含到项目中,为此应该在settings.py中的INSTALLED_APPS片段中添加我们的应用程序信息
接下来,需要让Django修改数据库,使其能够存储与模型Topic相关的信息。为此,在终端窗口执行makemigrations
命令让Django确定该如何修改数据库,执行后Django将创建一个迁移文件在数据库中为模型Topic创建一个表
下面,使用migrate
来应用这种迁移,让Django替我们修改数据库
3.Django管理网站
为应用程序定义模型时,Django提供的管理网站admin site让我们能够轻松地处理模型。接下来,我们就建立管理网站,并通过它使用模型Topic来添加一些主题
创建超级用户:
执行python manage.py createsuperuser
命令在Django中创建超级用户,执行命令后,Django提示输入超级用户的用户名(默认)、邮箱(可放空)、密码、确认密码
向管理网站注册模型:
在models.py所在目录中的admin.py文件中输入下面代码向管理网站注册Topic
from learning_logs.models import Topic
admin site.register(Topic)
现在使用超级用户账户访问登录网站:http://localhost:8000/admin/ ,输入刚创建的超级用户的用户名和密码,进入如下界面(Django administration)。这个网页能让我们添加和修改用户和用户组,还可以管理刚才定义的模型Topic相关的数据,接下来,我们来添加第一个主题
添加主题:
单击Topics进入主题网页,它几乎是空的,因为我们还没有添加任何主题
单击Add,看到一个用于添加新主题的表单,在第一个输入框中输Chess,再单击Save,这将返回主题管理页面,其中刚创建的主题已被添加,按照该步骤我们再创建一个Rock Climbing主题
4.定义模型Entry:
特定主题下有用户在学习笔记记录的知识条目,这是一种多对一关系,即多个知识条目关联到同一个主题
像Topic一样,我们创建Entry模型,它继承Django基类Model,拥有topic、text、date_added三个属性
- topic属性:是一个ForeignKey实例,它引用数据库中的另一条记录,将每个条目关联到特定的主题
- text属性:一个不限制长度的TextField实例
- date_added属性:条目的时间戳
- Meta类:嵌套的Meta类,用于存储管理模型的额外信息,在这里我们能够设置一个特殊属性,让Django在需要时使用Entries来表示多个条目。如果没有这个类,Django将使用Entrys来表示多个条目
- __ unicode __ ()方法:告诉Django,呈现条目时应该显示那些信息,我们只显示text的前50个字符,并用...指出显示内容并非整个条目
迁移模型Entry:
由于我们新添加了一个新模型,因此需要再次迁移数据库
这个过程是:
- 修改models.py
- 执行命令
python manage.py makemigrations app_name
- 再执行
python manage.py migrate
生成了一个新的迁移文件,告诉Django如何修改数据库,使其能存储与模型Entry相关的信息,然后执行migrate,应用迁移
向管理网站注册Entry:
在admin.py中注册模型Entry
返回http://localhost:8000/admin/,你将看到learing_logs下列出了Entries,单击Entries的Add链接或单击Entries再选择Add entry。
你将看到一个下拉列表,能选择要创建哪个主题的条目,还有一个输入条目的文本框。我们添加一个Chess主题的条目,如下:
返回条目管理页面,我们能看到添加的条目以及使用text[:50]呈现出来的条目信息
3、创建网页:学习笔记主页
使用Django创建网页的过程通常分三个阶段:定义URL、编写视图和编写模板。首先,你必须定义URL模式。URL模式描述了URL是如何设计的,让Django知道如何将浏览器请求与网站URL匹配,以确定返回哪个网页。
每个URL都被映射到特定的视图——视图函数获取并处理网页所需的数据。视图函数通常条用一个模板,后者生成浏览器能够理解的网页。我们接下来创建学习笔记的主页。我们将定义主页的URL、编写其视图函数并创建一个简单的模板
鉴于我们只是要确保”学习笔记“按要求的那样工作,我们将暂时让这个网页尽可能简单。Web应用程序能够正常运行后,设置样式可使其更有趣,但中看不中用的应用程序毫无意义。目前的主页只显示标题和简单的描述。
1.映射URL:
用户通过在浏览器中输入URL以及单击链接来请求网页,因此我们需要确定项目所需的URL。
当前,基础URL(http://localhost:8000/ )返回默认的Django网站,让我们知道正确建立了项目。我们将修改这一点,让这个基础URL映射到”学习笔记“的主页
首先,我们修改项目文件夹中的urls.py
urls.py文件的urlpatterns主体包含了项目中的应用程序的URL。其中的admin.site.urls定义了可在管理网站中请求的所有URL
我们添加了learning_logs.urls并包含namespace将learning_logs的URL同项目中的其他URL区分开来,这在项目扩展时很有帮助
所以我们又需要在文件夹learning_logs中创建另一个urls.py文件:
在应用程序的urls.py中,我们导入了url模块用于将URL映射到视图,还导入了views模块,其中的句点表示让Python从当前的urls.py模块所在的文件夹中导入视图。变量urlpatterns是一个包含了可在应用程序learning_logs中请求的网页
实际的URL模式是一个对函数url()
的调用,这个函数接受三个实参:
- 第一个是一个正则表达式。例如:
r'^$'
,其中的r
让Python将接下来的字符串视为原始字符串,引号包括正则表达式的起止。脱字符^
让Python查看字符串的开头,美元符$
让Python查看字符串末尾 - 第二个实参指定了要调用的视图函数。当请求的URL与前述正则表达式匹配时,Django将调用views.index(视图编写在后面)
- 第三个实参将这个URL模式的名称指定为index,让我们能够在代码的其他地方引用它。当需要提供主页的链接时,都将使用这个名称,而不用编写URL
2.编写视图:
视图函数接受请求中的信息,准备好生成网页所需的数据,再将这些数据发送给服务器
我们在learning_logs应用程序的views.py中为主页编写视图,如下:
URL请求与我们刚才定义的模式匹配时,Django将在文件views.py中查找函数index(),再将请求对象传递给这个视图函数。在这里,我们不用处理任何数据,因此这个函数只调用render(),向它提供两个实参:原始请求对象以及一个用于创建网页的模板。接下来就是编写模板了
3.编写模板:
模板定义了网页的结构。模板定义了网页是什么样的,每当网页被请求时,Django将填入相关的数据。模板让你能够访问试图提供的任何数据。
我们在learning_logs中新建一个文件夹,将其命名为templates,在templates中再创建一个learning_logs文件夹(这似乎有些多余?但建立了Django能够明确解读的结构,即使项目很大,包含很多应用程序亦如此)。然后创建index.html文件,编写index.html代码
<p>Learning Log</p>
<P>Learning Log helps you keep track of your learning, for any topic you're learning about.</p>
现在,我们再请求项目的基础URL——http://localhost:8000/ ,将看到刚才创建的网页,而不是默认的Django网页。Django接受请求的URL匹配了模式r'^$'
,因此调用函数views.index(),于是使用index.html包含的模板来渲染网页,结果如下
4、创建其他网页
制定创建网页的流程后,可以开始扩充”学习笔记“的项目了。我们将创建两个显示数据的网页,其中一个列出所有的主题,另一个显示指定主题的所有条目。对于每个网页我们都将指定URL模式,编写一个视图函数,并编写一个模板。
1.模板继承:
创建网站时,几乎都有一些所有网页都将包含的元素。在这种情况下,可以编写一个包含通用元素的父模板,并让每个网页都继承这个模板,而不必在每个网页中重复定义这些通用元素。这种方法让你能专注于开发每个网页的独特方面,还能让修改项目的整体外观容易很多
我们在learning_logs/templates/learning_logs下创建我们的模板
创建一个base.html
其中我们使用了模板标签{% %}
,模板标签是一小段代码,生成要在网页中显示的信息。这里,模板标签{% url 'learning_logs:index' %}
生成一个url,该url于learning_logs/urls.py中定义的名为index的URL模式匹配
利用模板标签来生成URL,有利于更新链接。要修改项目中的URL,只需修改urls.py中的URL模式,这样网页被请求时,Django自动插入修改后的URL
重写index.html,使其继承base.html,如下
标签{% extends %}
指定继承的父模板
标签{% block %}
定义content块,再使用{% endblock content %}
指定了内容定义的结束位置
这里,模板继承的优点开始显现出来了:在子模版中,只需包含当前网页特有的网内容。
2.显示所有主题的页面:
URL模式
这个模式与这样的URL匹配:基础URL后面跟着topics,可以在末尾包含斜杠,也可以省略它,但单词topics后面不能又任何东西,否则就与该模式不匹配。该模式匹配的请求都交给views.py中的函数topics()处理
视图
导入所需数据相关联的Topic模型,将Topic对象按属性date_added排序,存入一个上下文字典中,创建使用数据的网页时,除对象request和模板的路径外,我们还将变量context传递给render()
模板
与模板index.html类似的,topics.html继承base.html父模板
我们使用了一个相当于for循环的模板标签,遍历字典context中的列表topics,{{ topic }}
是一个模板变量,Django会将这部分替换为topic的当前值
我们还使用了模板标签{{% empty % }}
告诉Django在topics列表为空的时候怎么办
现在修改父模板,使其包含到显示所有主题的页面的链接
到浏览器主页单击Topics链接看到如下网页
3.显示特定主题的页面
URL模式
我们再看看这个URL模式中的正则表达式——r'^topics/(?P<topic_id>\d+)/$'
。r让Django将这个字符串是为原始字符串,并指出正则表达式包含在引号内。表达式的第二部分(/(?P<topic_id>\d+)/)
与包含在两个斜杠内的整数匹配,并将这个整数存储在一个名为topic_id的实参中。这部分表达式两边的括号捕获URL中的值;?P<topic_id>
即将匹配的值存储在topic_id中;\d+
与包含在两个斜杠内的任何数字都匹配,不管这个数字多少位
发现URL与这个模式匹配时,Django将调用视图函数topic(),并将存储在topic_id中的值作为实参传递给它
视图
topic函数中包含了一个形参,我们使用get()获取topic_id指定的主题,使用entry_set.order_by()获取降序排序的条目。这是一种查询,在自己的项目中编写类似的查询时,我们应该使用Django shell先进行尝试。然后把查询结果存入字典中发送给模板topic.html
模板
该模板也继承了base.html父模板
特别的,在该模板中我们使用了模板过滤器|
用一个竖线表示。例如date: 'M d, Y H:i'
以这样的格式显示时间戳:January 1,2015 23:00
,过滤器linebreaks
将包含换行符的长条目转换成浏览器能够理解的格式,以免显示一个不间断的文本块
将显示所有主题的页面中的每个主题都设置为链接
在topics请求页面中,链接到显示相应主题的页面,如http://localhost:8000/topics/1/ ,结果如下