使用Django框架—Python编程从入门到精通(11)

发表于:2019-1-02 11:31

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:叶维忠    来源:51Testing软件测试网原创

  19.3.7、实现基本的数据库操作
  在动态Web应用中,数据库技术永远是核心技术中的核心技术。Django模型是与数据库相关的,与数据库相关的代码一般保存在文件models.py中。Django框架支持SQLite3、MySQL和PostgreSQL 等数据库工具,开发者只需要在文件 settings.py 中进行配置即可,不用修改文件models.py中的代码。下面的实例代码演示了在Django框架中创建SQLite3数据库信息的过程。
  实例19-12 创建SQLite3数据库信息
  源码路径 daima\19\19-12
  (1)新建一个名为"learn_models"的项目,然后进入"learn_models"文件夹中,并新建一个名为"people"的app。
django-admin startproject learn_models # 新建一个项目
cd learn_models # 进入到该项目的文件夹
django-admin startapp people # 新建一个 people 应用(app)
  (2)将新建的应用(people)添加到文件 settings.py中的INSTALLED_APPS中,也就是告诉Django有这么一个应用。
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'people',
)
  (3)打开文件people/models.py,新建一个继承自类models.Model的子类Person,此类中有name和age这两个字段。具体实现代码如下所示。
from django.db import models
class Person(models.Model):
name = models.CharField(max_length=30)
age = models.IntegerField()
def __str__(self):
return self.name
  在上述代码中,name和age这两个字段中不能有双下划线"__",这是双下划线因为在Django QuerySet API中有特殊含义(用于关系,包含,不区分大小写,以什么开头或结尾,日期的大于、小于,正则表达式等)。另外,也不能有Python中的关键字。所以说name是合法的,student_name也是合法的,但是student__name不合法,try、class和continue也不合法,因为它们是Python的关键字。
  (4)开始同步数据库操作,在此使用默认数据库SQLite3,无须进行额外配置。具体命令如下所示。
# 进入 manage.py 所在的那个文件夹并输入这个命令
python manage.py makemigrations
python manage.py migrate
  通过上述命令可以创建一个数据库表,当在前面的文件models.py中新增类Person时,运行上述命令后就可以自动在数据库中创建对应数据库表,不用开发者手动创建。在CMD控制台中运行后,会发现Django生成了一系列的表,也生成了上面刚刚新建的表 people_person。CMD 运行界面如图 19-20所示。
  (5)在CMD控制台中,输入命令进行测试。整个测试过程如下所示。
$ python manage.py shell
>>>from people.models import Person
>>>Person.objects.create(name="haoren", age=24)
<Person: haoren>
>>>Person.objects.get(name="haoren")
<Person: haoren>
  19.3.8、使用Django后台系统开发博客系统
  在动态Web应用中,后台管理系统十分重要,网站管理员通过后台实现对整个网站的管理。Django框架的功能十分强大,为开发者提供了现成的admin后台管理系统,程序员只需要编写很少的代码就可以实现功能强大的后台管理系统。下面的实例代码演示了使用Django框架开发博客系统的过程。
  实例19-13 开发个人博客系统
  源码路径 daima\19\19-13
  (1)新建一个名为"zqxt_admin"的项目,然后进入"zqxt_admin"文件夹中,并新建一个名为"blog"的app。
django-admin startproject zqxt_admin
cd zqxt_admin
# 创建 blog 这个 app
python manage.py startapp blog
  (2)修改"blog"文件夹中的文件models.py。具体实现代码如下所示。
from __future__ import unicode_literals
from django.db import models
from django.utils.encoding import python_2_unicode_compatible
@python_2_unicode_compatible
class Article(models.Model):
title = models.CharField('标题', max_length=256)
content = models.TextField('内容')
pub_date = models.DateTimeField('发表时间', auto_now_add=True, editable=True)
update_time = models.DateTimeField('更新时间', auto_now=True, null=True)
def __str__(self):
return self.title
class Person(models.Model):
first_name = models.CharField(max_ length=50)
last_name = models.CharField(max_ length=50)
def my_property(self):
return self.first_name + ' ' + self.
last_name
my_property.short_description = "Full name of
the person"
full_name = property(my_property)
  (3)将"blog"加入到settings.py文件中的INSTALLED_APPS中。具体实现代码如下所示。
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'blog',
)
  (4)通过如下所示的命令同步所有的数据库表。
# 进入包含有 manage.py 的文件夹
python manage.py makemigrations
python manage.py migrate
  (5)进入文件夹"blog"中,修改里面的文件admin.py(如果没有新建一个)。具体实现代码如下所示。
from django.contrib import admin
from .models import Article, Person
class ArticleAdmin(admin.ModelAdmin):
list_display = ('title', 'pub_date', 'update_time',)
class PersonAdmin(admin.ModelAdmin):
list_display = ('full_name',)
admin.site.register(Article, ArticleAdmin)
admin.site.register(Person, PersonAdmin)
  输入下面的命令启动服务器。
  python manage.py runserver
  然后,在浏览器中输入"http://localhost:8000/admin"会显示一个用户登录表单界面,如图19-21所示。
  可以创建一个超级管理员用户,在CMD控制台中,使用命令进入包含manage.py的文件夹"zqxt_admin"中。接下来,输入如下命令创建一个超级账号,根据提示分别输入账号、邮箱地址和密码。
  python manage.py createsuperuser
  此时可以使用超级账号登录后台管理系统。登录成功后的界面如图19-22所示。
  管理员可以修改、删除或添加账号信息,如图19-23所示。
  也可以对系统内已经发布的博客信息进行管理和维护,如图19-24所示。
  也可以直接修改用户账号信息的密码,如图19-25所示。
 
  19.4、使用Flask框架
  Flask是一个免费的Web框架,也是一个年轻充满活力的微框架,有着众多的拥护者,文档齐全,社区活跃度高。Flask的设计目标是实现一个WSGI的微框架,其核心代码保持简单性和可扩展性,很容易学习。本节将详细讲解使用Flask框架开发Python Web程序的知识。
  19.4.1、开始使用Flask框架
  因为Flask框架并不是Python语言的标准库,所以在使用之前必须先进行安装。可以使用pip命令实现快速安装,因为它会自动帮你安装其依赖的第三方库。在CMD控制台的命令提示符下使用如下命令进行安装。
  pip install flask
  成功安装时的界面如图19-26所示。
  
  在安装Flask框架后,可以在交互式环境下使用import flask语句进行验证。如果没有错误提示,则说明成功安装Flask框架。另外,也可以通过手动下载的方式进行手动安装,必须先下载安装Flask依赖的两个外部库,即Werkzeug和Jinja2,分别解压后进入对应的目录,在命令提示符下使用python setup.py install来安装它们。Flask依赖外部库的下载地址可到网上搜索。
  然后,在下面的下载地址下载Flask。下载后再使用python setup.py install命令来安装它。
  http://pypi.python.org/packages/source/F/Flask/Flask-0.10.1.tar.gz
  下面的实例代码演示了使用Flask框架开发一个简单Web程序的过程。
  实例19-14 使用Flask框架开发一个简单Web程序
  源码路径 daima\19\19-14
  实例文件flask1.py的具体实现代码如下所示。
import flask                 #导入flask模块
app = flask.Flask(__name__)   #实例化类Flask
@app.route('/')           #装饰器操作,实现URL地址
def helo():               #定义业务处理函数helo()
return '你好,这是第一个Flask程序!'
if __name__ == '__main__':
app.run()             #运行程序
  在上述实例代码中首先导入了Flask框架,然后实例化主类并自定义只返回一串字符的函数helo()。接着使用@app.route('/')装饰器将URL和函数helo()联系起来,使得服务器在收到对应的URL请求时,调用这个函数,返回这个函数生产的数据。
  执行后会显示一行提醒语句,如图19-27所示。这表示Web服务器已经正常启动和运行了,它的默认服务器端口为5000,IP地址为127.0.0.1。
  
  在浏览器中输入网址"http://127.0.0.1:5000/"后,便可以测试上述Web程序,执行效果如图19-28所示。通过按下键盘中的Ctrl+C组合键可以退出当前的服务器。
  
  当服务器收到浏览器发出的访问请求后,服务器还会显示出相关信息,如图19-29所示。其中显示了访问该服务器的客户端地址、访问的时间、请求的方法以及表示访问结果的状态码。
 
  在上述实例代码中,方法run()的功能是启动一个服务器,在调用时可以通过参数来设置服务器。常用的主要参数如下所示。
  " host:服务的IP地址,默认为None。
  " port:服务的端口,默认为None。
  " debug:是否开启调试模式,默认为None。
  19.4.2、传递URL参数
  在Flask框架中,通过使用方法route()可以将一个普通函数与特定的URL关联起来。当服务器收到这个URL请求时,会调用方法route()返回对应的内容。Flask框架中的一个函数可以由多个URL装饰器来装饰,实现多个URL请求由一个函数产生的内容响应。下面的实例演示了将不同的URL映射到同一个函数的过程。
  实例19-15 将不同的URL映射到同一个函数
  源码路径 daima\19\19-15
  实例文件flask2.py的具体实现代码如下所示。
import flask                  #导入flask模块
app = flask.Flask(__name__)    #实例化类
@app.route('/')   #装饰器操作,实现URL地址映射
@app.route('/aaa') #装饰器操作,实现第2个URL地址映射
def helo():
return '你好,这是一个Flask程序!'
if __name__ == '__main__':
app.run()                  #运行程序
  执行本实例后,无论是在浏览器中输入"http:// 127.0.0.1:5000/",还是输入"http://127. 0.0.1:5000/aaa",在服务器端都将这两个URL请求映射到同一个函数helo(),所以输入两个URL地址后的效果一样。执行效果如图19-30所示。
  在现实应用中,实现HTTP请求传递最常用的两种方法是"GET"和"POST"。在Flask框架中,URL装饰器的默认方法为"GET",通过使用Flask中URL装饰器的参数"方法类型",可以让同一个URL的两种请求方法都映射在同一个函数。
  在默认情况下,当通过浏览器传递参数相关数据或参数时,都是通过GET或POST请求中包含参数来实现的。其实通过URL也可以传递参数,此时直接将数据放入到URL中,然后在服务器端获取传递的数据。
  在Flask框架中,获取的URL参数需要在URL装饰器和业务函数中分别进行定义或处理。有如下两种形式的URL变量规则(URL装饰器中的URL字符串写法)。
  /hello/<name>      #例如获取URL"/hello/wang"中的参数"wang"并赋予name变量
  /hello/<int: id>   #例如获取URL"/hello/5"中的参数"5",并自动转换为整数5给id变量
  要想获取和处理URL中传递来的参数,需要在对应业务函数的参数列表中列出变量名。具体语法格式如下所示。
@app.route("/hello/<name>")
def get_url_param (name):
pass
  这样在列表中列出变量名后,就可以在业务函数get_url_param()中引用这个变量值,并可以进一步使用从URL中传递过来的参数。
  下面的实例演示了使用get请求获取URL参数的过程。
  实例19-16 使用get请求获取URL参数
  源码路径 daima\19\19-16
  实例文件flask3.py的具体实现代码如下所示。
import flask        #导入flask模块
html_txt = """      #初始化变量html_txt,作为GET请求的页面
<!DOCTYPE html>
<html>
<body>
<h2>如果收到了GET请求</h2>
<form method='post'> #设置请求方法是"post"
<input type='submit' value='按下我发送
POST请求' />
</form>
</body>
</html>
"""
app = flask.Flask(__name__)  #实例化类Flask
#URL映射,不管是'GET'方法还是'POST'方法,都
#映射到helo()函数
@app.route('/aaa',methods=['GET','POST'])
def helo():               #定义业务处理函数helo()
if flask.request.method == 'GET':  #如果接收到的请求是GET
return html_txt              #返回html_txt的页面内容
else:                              #否则,接收到的请求是POST
return '我司已经收到POST请求!'
if __name__ == '__main__':
app.run()                          #运行程序
  本实例演示了使用参数"方法类型"的URL装饰器实例的过程。在上述实例代码中,预先定义了GET请求要返回的页面内容字符串html_txt,在函数helo()的装饰器中提供了参数methods为"GET"和"POST"字符串列表,表示对于URL为"/aaa"的请求,不管是'GET'方法还是'POST'方法,都映射到helo()函数。在函数helo()内部使用flask.request.method来判断收到的请求方法是"GET"还是"POST",然后分别返回不同的内容。
  执行本实例,在浏览器中输入"http://127.0.0.1:5000/aaa"后的效果如图19-31所示。单击"按下我发送POST请求"按钮后的效果如图19-32所示。
  
  19.4.3、使用session和cookie
  通过本书前面内容的学习可知,通过使用cookie和session可以存储客户端和服务器端的交互状态。其中cookie能够运行在客户端并存储交互状态,而session能够在服务器端存储交互状态。在Flask框架中提供了上述两种常用交互状态的存储方式,其中session存储方式与其他Web框架有一些不同。Flask框架中的session使用了密钥签名的方式进行了加密。也就是说,虽然用户可以查看你的cookie,但是如果没有密钥就无法修改它,并且只保存在客户端。
  在Flask框架中,可以通过如下代码获取cookie。
  flask. request.cookies.get('name ')
  在Flask框架中,可以使用make_response对象设置cookie,例如下面的代码。
resp = make_response (content)                #content返回页面内容
resp.set_cookie ('username','the username')   #设置名为username的cookie
  下面的实例演示了使用cookie跟踪用户的过程。
  实例19-17 使用cookie跟踪用户
  源码路径 daima\19\19-17
  实例文件flask4.py的具体实现代码如下所示。
import flask      #导入flask模块
html_txt = """     #初始化变量html_txt,作为GET请求的页面
<!DOCTYPE html>
<html>
<body>
<h2>可以收到GET请求</h2>
<a href='/get_xinxi'>单击我获取cookie信息</a>
</body>
</html>
"""
app = flask.Flask(__name__)        #实例化类Flask
@app.route('/set_xinxi/<name>')   #URL映射到指定
#目录中的文件
def set_cks(name):   #函数set_cks()用于从URL中获
#取参数并将其存入cookie中
name = name if name else 'anonymous'
resp = flask.make_response(html_txt)     #构造响应对象
resp.set_cookie('name',name)             #设置cookie
return resp
@app.route('/get_xinxi')
def get_cks():                     #函数get_cks()用于从cookie中读取数据并显示在页面中
name = flask.request.cookies.get('name') #获取cookie信息
return '获取的cookie信息是:' + name        #显示获取到的cookie信息
if __name__ == '__main__':
app.run(debug=True)
  在上述实例代码中,首先定义了两个功能函数。其中,第一个功能函数用于从URL中获取参数并将其存入cookie中;第二个功能函数用于从cookie中读取数据并显示在页面中。
  当在浏览器中使用"http://127.0.0.1:5000/set_xinxi/langchao"浏览时,表示设置了名为name(langchao)的cookie信息,执行效果如图19-33所示。当单击"单击我获取cookie信息"链接后来到"/get_xinxi"时,会在新页面中显示在cookie中保存的name名称"langchao"的信息,效果如图19-34所示。
 
  19.4.4、文件上传
  在Flask框架中实现文件上传系统的方法非常简单,与传递GET或POST参数十分相似。在Flask框架实现文件上传系统的基本流程如下所示。
  (1)将在客户端上传的文件保存在flask.request.files对象中。
  (2)使用flask.request.files对象获取上传的文件名和文件对象。
  (3)调用文件对象中的方法save()将文件保存到指定的目录中。
  下面的实例演示了在Flask框架中实现文件上传系统的过程。
  实例19-18 在Flask框架中实现文件上传系统
  源码路径 daima\19\19-18
  实例文件flask5.py的具体实现代码如下所示。
import flask                 #导入flask模块
app = flask.Flask(__name__)  #实例化类Flask
#URL映射操作,设置处理GET请求和POST请求的方式
@app.route('/upload',methods=['GET','POST'])
def upload():                #定义文件上传函数upload()
if flask.request.method == 'GET':  #如果是GET请求
return flask.render_template('upload.html')  #返回上传页面
else:                    #如果是POST请求
file = flask.request.files['file']           #获取文件对象
if file:                                     #如果文件不为空
file.save(file.filename)               #保存上传的文件
return '上传成功!'   #显示提示信息
if __name__ == '__main__':
app.run(debug=True)
  在上述实例代码中,只定义了一个实现文件上传功能的函数upload(),它能够同时处理GET请求和POST请求。其中将GET请求返回上传页面,当获得POST请求时获取上传的文件,并保存到当前的目录下。
  当在浏览器中使用"http://127.0.0.1:5000/upload"运行时,显示一个文件上传表单界面,效果如图19-35所示。单击"浏览"按钮可以选择一个要上传的文件,单击"上传"按钮后会上传这个文件,并显示上传成功提示。执行效果如图19-36所示。
 
  19.5、技术解惑
  19.5.1、"客户端/服务器"开发模式
  因为Web应用程序开发是现实中最常见的软件开发类型,整个开发过程涵盖的知识非常广,所以在本节首先针对常见的Web开发模式进行简要介绍,为读者进入后续章节的学习打下坚实的基础。在本书前面的网络开发章节中,曾经讲解了客户端/服务器编程模型的基本知识,客户端/服务器编程模型其实就是客户端/服务器开发模式。Web应用遵循前面反复提到的客户端/服务器架构。这里说的Web客户端是浏览器,即允许用户在万维网上查询文档的应用程序。另一边是Web服务器端,指的是运行在信息提供商的主机上的进程。这些服务器等待客户端及其文档请求,进行相应的处理,并返回相关的数据。正如大多数客户端/服务器系统中的服务器端一样,Web服务器端"永远"运行。用户运行Web客户端程序(如浏览器),连接因特网上任意位置的Web服务器来获取数据。
  客户端可以向Web服务器端发出各种不同的请求,这些请求可能包括一个用于查看网页的需求,或者提交一个包含待处理数据的表单。Web服务器端首先处理请求,然后以特定的格式(HTML等)返回给客户端浏览。
  Web客户端和服务器端交互需要用到特定的"语言",即Web交互需要用到的标准协议,这称为HTTP(HyperText Transfer Protocol,超文本传输)。HTTP是TCP/IP的上层协议,这意味着HTTP协议依靠TCP/IP来进行低层的交流工作。它的职责不是发送或者传递消息(TCP/IP协议处理这些),而是通过发送、接收HTTP消息来处理客户端的请求。HTTP属于无状态协议,因为其不跟踪从一个客户端到另一个客户端的请求信息,这一点很像现在使用的客户端/服务器架构。服务器持续运行,但是客户端的活动以单个事件划分,一旦完成一个客户请求,这个服务事件就停止了。客户端可以随时发送新的请求,但是会把新的请求视为独立的服务请求。由于每个请求缺乏上下文,因此你可能注意到有些URL中含有很长的变量和值,这些将作为请求的一部分,以提供一些状态信息。另一种方式是使用"cookie",即保存在客户端的客户状态信息。
  19.5.2、Python Web客户端开发是大势所趋
  在现实应用中,浏览器只是众多Web客户端的一种,任何一个向Web服务器端发送请求来获得数据的应用程序都可以称为"客户端"。当然,也可以创建并使用其他的客户端以在互联网中检索和浏览数据。从市场需求方面来看,创建其他客户端的主要原因如下。
  " 浏览器的能力有限,浏览器主要用于浏览网页内容并同其他Web站点交互。
  " 客户端程序可以完成更多的工作,不仅可以下载数据,还可以存储、操作数据,甚至可以将其传送到另外一个地方或者传给另外一个应用。
  在Python程序中,可以使用urllib模块下载或者访问Web中的信息(例如使用urllib.urlopen()或者urllib.urlretrieve())。整个实现过程非常简单,开发者所要做的只是为程序提供一个有效的Web地址而已。
  19.5.3、注意Python 3的变化
  从Python 3开始,已经将urllib2、urlparse和robotparser并入到了urllib模块中,并且修改了urllib模块,其中包含如下5个子模块。
  " urllib.error。
  " urllib.parse。
  " urllib.request。
  " urllib.response。
  " urllib.robotparser。
  19.6、课后练习
  (1)编写一个程序,使用Tornado实现文件上传。
  (2)编写一个程序,在Django框架中使用Ajax技术。

相关阅读:
22/2<12
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号