1、知识回顾
1、POST/PUT/DELETE/PATCH
访问一个url地址的时候才可以带请求体
2、状态码:
200 请求成功
400 客户端请求有误
403 请求被拒绝
404 请求资源找不到
500 服务器发生错误
3、URL地址:协议、域名、端口、请求资源路径、请求参数
2、Django介绍
客户端->服务器
web服务器+Flask框架写项目代码
2.1 服务器介绍
服务器包括一个web服务器和web框架,他们直接遵循WSGI的协议
web服务器作用;解析请求报文,调用框架程序处理请求;组织响应报文,返回内容给客户端。
web框架程序作用:路由分发(根据URL找到对应的处理函数);调用处理函数进行业务的处理。
顺序:
1、解析请求报文,调用框架程序处理请求
2、路由分发(根据URL找到对应的处理函数)
3、调用处理函数进行业务的处理
4、组织响应报文,返回内容给客户端
框架程序中所做的事:先构造一个HTTP请求对象(request),然后进行一个中间层处理(相当于Flask里面的请求钩子,钩子函数就是在请求之前或请求之后做一些事情),具体视图处理-业务处理(如数据库、模板、表单),再进行中间层处理,最终返回给服务器程序响应对象(response)
2.2 web程序框架的意义
用于搭建web应用程序,免去不同web应用相同代码部分的重复编写,只需关心web应用核心的业务逻辑实现
2.3 学习框架的步骤
1、先写一个helloworld
程序(搭建工程程序:工程组建、配置、路由定义、视图函数定义);
2、再考虑如何获取请求数据(操作request
对象);
3、再考虑构造响应数据(构造response
对象);
4、然后考虑如何使用中间层;
5、最终就是考虑框架提供的其他功能组件怎么使用(数据库、模板和admin)
2.4 Django
强调快速开发、DRY原则(DoNotRepeatYourself
)
特点:
1、重量级框架(相对于Flask来说,很多功能组件不需要自己再安装)
提供项目工程管理自动化脚本工具(对应Flask中的flask-script
)
数据库ORM支持(对应Flask中的FlaskSQLAlchemy
)
2、MVT模式(Model模型、View视图、Template模板)
Model模型:操作数据库
View视图:接收请求,进行业务处理、返回响应
Template模板:封装构造要返回的html,展示页面内容
3、MVT就是一种MVC,了解一下MVC即可
不同点:
MVC中的View相当于MVT中的Template
MVC中的Controller相当于MVT里面的View一样
相同点:M相同
3、工程搭建
步骤:
1、创建python3的虚拟环境
mkvirtualenv 虚拟环境的名字 -p python3
2、安装Django
pip install django==1.11.11
3、虚拟环境的相关命令
mkvirtualenv
创建虚拟环境
rmvirtualenv
删除虚拟环境
workon
进入虚拟环境(后面直接加要进入的虚拟环境的名字)、查看所有虚拟环境
deactivate
退出虚拟环境
pip install
安装依赖包
pip uninstall
卸载依赖包
pip list
已列表形式查看已安装的依赖包
pip freeze
查看已安装的环境的依赖包(没有上面的展示效果好看)
需要注意的小点:
1、默认的端口是8000,默认的ip是127.0.0.1
2、一个项目分为很多功能模块,Flask里面的功能模块是蓝图,Django里面的功能模块是子应用
3、Django自带admin站点,我们想使用直接在admin.py中进行配置即可
3.1项目创建
创建项目:django-admin startprotect 项目名
创建子应用:python manage.py startapp 子应用名
(先切换到项目的目录下,再创建)
子应用需要到INSTALLED_APPS中进行注册
工程目录说明:
setting.py
是项目整体配置文件
urls.py
是项目的URL配置文件(也就是我们常说的总的地址配置文件)
wsgi.py
是项目与WSGI兼容的Web服务器的一个入口
manage.py
是项目管理文件,通过它管理项目
子应用目录说明:
admin.py
文件跟网站的后台管理站点配置相关
apps.py
文件用于配置当前子应用的相关信息
migrations
目录用于存放数据库迁移历史文件
models.py
文件用于保存数据库的模型类
tests.py
文件用于开发测试用例,编写单元测试
views.py
文件用于编写web应用视图
3.2helloworld程序创建
1、在定义视图函数的时候,必须接收request
(作为形参接收请求对象)
Flask框架中的视图函数可以直接返回字符串,但是Django视图返回的必须是响应对象
2、返回响应对象HttpResponse
,相应对象中,传入响应的内容就可以了
3、在子应用下面创建一个文件urls.py
,然后创建一个urlpatterns
列表,然后再列表里面添加当前子应用中url
地址和视图函数的对应关系url("url正则表达式","对应视图函数")
。具体形式看下面,注意index前面的斜杆不写
url('^index/$',views.index)
4、在项目总的urls.py文件中包含子应用中的urls.py文件
1urlpatterns = [ 2 url(r'^admin/', admin.site.urls), 3 url(r'^',include('users.urls')), # 包含users子应用下方的url文件 4]
第二个url中正则表达式中不光可以写^匹配开头,还可以写一个前缀,进行匹配(这种情况在浏览器访问路径的时候就必须写前缀了)
4、路由说明
4.1 Django框架匹配的过程(十分重要)
我们访问地址,拿到地址/index
之后,Django会先去总的urls中urlpatterns列表
中从上到下开始匹配,匹配的时候将最前面的'/'去掉再匹配,匹配成功之后,去掉匹配成功的内容;将匹配剩下的内容到包含的子应用urls里面进行同样匹配,然后匹配成功,找到对应的视图函数,就会进行调用,然后给里面传一个request,最后就返回一个响应。
4.2 djano中url
地址配置默认风格:在结尾加'/'
我们在浏览器中输入地址的时候没有加'/',加载的时候会先有一个重定向,然后自动帮我们加斜杠去访问
在工作中,以公司配置url地址的风格为准,可以进行更改
在子应用中进行url地址的配置时,建议严格匹配开头和结尾(防止访问时,视图混乱的情况,框架程序找错对应的视图函数)
4.3url地址反向解析
作用:根据视图函数动态获取对应的url,一般配合重定向时使用
Flask中使用方法:
from flask import url_for
url_for('蓝图名.视图函数名')
在重定向的时候使用:redirect('/index')
重定向中使用反向解析的好处,将来视图函数的地址改变的时候,我们重定向是不需要更改的。
Django中使用方法:
1、在子应用中地址配置时定义一个name参数,指明路由的名字
2、在总的地址配置里面进行包含的时候,定义一个namespace,一般名字和子应用的名字一样(注意写在include里面)
3、导入:
from django.urls import reverse
使用:
reverse('namespace:name')
生成对应视图的url地址
例如:
req_rul = reverse('users:index')
5、Django配置文件
5.1BASE_DIR
BASE_DIR
Django项目的根目录路径,利用它生成一些项目里面的路径
在一个文件中打印__file__
时,输入的结果是当前文件的绝对路径
os.path.abspath(__file__)
获取的是绝对路径
os.path.dirname()
获取的是本文件的上一级的绝对路径
5.2DEBUG
DEBUG
默认为True,部署的时候改为False
作用:
1、修改代码文件,程序自动重启
2、Django程序出现异常时,向前端显示详细的错误追踪信息
5.3语言时区本地化
语言时区本地化
LANGUAGE_CODE='en-us'
语言改为中文'zh-hans'
TIME_ZONE = 'UTC'
时区,改为中国时区'Asia/Shanghai'
5.4静态文件
项目中的CSS、图片和js都是静态文件。
设置静态文件存储的目录(需要自己设置)
STATICFILES_DIRS
是一个列表,存放查找静态文件的目录,里面存放的路径我们不使用绝对路径,而是下面这样:
os.path.join(BASE_DIR, 'static_files')
设置访问金泰文件的url地址前缀(默认有,不设置也可以)
STATIC_URL = '/static/'
注意:
Django 仅在调试模式下(DEBUG=True)的模式下对外提供静态文件。
当DEBUG=False工作在生产模式时,Django不再对外提供静态文件,需要使用collectstatic
命令来收集静态文件并交由其他静态文件服务器来提供。项目部署的时候,debug会改为False,然后我们使用Nginx
来提供静态文件。
6.请求与相应
6.1回顾
web开发中,客户端向服务器传递参数的途径:
1、通过url地址传递参数
url地址:/users/<int:user_id>
2、通过请求体来传递参数
post表单,文件,json
3、通过请求头传递数据
1$ajax({ 2 type:'post', 3 headers:{ 4 'X-CSRFToken':'值' 5 } 6})
4、通过查询字符串传递参数
在url地址中?后面的参数/index?a=1&b=2
6.2请求request
6.2.1URL地址中取参数
1、未命名参数按定义顺序传递
1url(r'^weather/(\w+)/(\d{4})/$', views.weather), 2 3def weather(request, city, year): 4 print('city=%s' % city) 5 print('year=%s' % year) 6 return HttpResponse('OK')
2、命名参数按名字传递(推荐使用)
1url(r'^weather/(?P<city>\w+)/(?P<year>\d{4})/$', views.weather), 2 3def weather(request, year, city): 4 print('city=%s' % city) 5 print('year=%s' % year) 6 return HttpResponse('OK')
6.2.2查询字符串中提取参数
Flask中利用request.args
获取
Django中利用request.GET
获取
获取请求路径中的查询字符串参数(形如?k1=v1&k2=v2),可以通过request.GET
属性获取,返回QueryDict
类的对象,类似于字典,但是和字典有区别,运行一键多个值(多个值获取利用request.GET.getlist
)。
1# /qs/?a=1&b=2&a=3 2 3def qs(request): 4 a = request.GET.get('a') 5 b = request.GET.get('b') 6 alist = request.GET.getlist('a') 7 print(a) # 3 8 print(b) # 2 9 print(alist) # ['1', '3'] 10 return HttpResponse('OK')
重要:查询字符串不区分请求方式(get或post请求方式等都可以带查询字符串),即假使客户端进行POST方式的请求,依然可以通过request.GET获取请求中的查询字符串数据。
Django中默认有csrftoken
验证,我们按自己需要关掉(在setting中的MIDDLEWARE
中第四行)
表单get提交,是提交的查询字符串,post提交的是请求体
6.2.3获取post表单提交的数据
Flask中:request.form
Django中:request.POST
前端发送的表单类型的请求体数据,可以通过request.POST
属性获取,返回QueryDict
对象。
1def get_body(request): 2 a = request.POST.get('a') 3 b = request.POST.get('b') 4 alist = request.POST.getlist('a') 5 print(a) 6 print(b) 7 print(alist) 8 return HttpResponse('OK')
重要:request.POST只能用来获取POST方式的请求体表单数据。
6.2.4获取json数据
1、利用request.body
获取请求体中原始数据bytes类型
2、然后将bytes转换位str利用decode()
3、将json字符串转换为python字典,利用下面两种
json.dumps(dict)
将python字典转换为json字符串
json.loads(json字符串)
将json字符串转换为python字典
非表单类型的请求体数据,Django无法自动解析,可以通过request.body属性获取最原始的请求体数据,自己按照请求体格式(JSON、XML等)进行解析。request.body返回bytes类型。
例如要获取请求体中的如下JSON数据
1{"a": 1, "b": 2}
可以进行如下方法操作:
1import json 2 3def get_body_json(request): 4 json_str = request.body 5 json_str = json_str.decode() # python3.6 无需执行此步 6 req_data = json.loads(json_str) 7 print(req_data['a']) 8 print(req_data['b']) 9 return HttpResponse('OK')
6.2.5通过请求头获取数据
可以通过request.META属性获取请求头headers中的数据,request.META为字典类型。
常见的请求头如:
CONTENT_LENGTH
– The length of the request body (as a string).
CONTENT_TYPE
– The MIME type of the request body.
HTTP_ACCEPT
– Acceptable content types for the response.
HTTP_ACCEPT_ENCODING
– Acceptable encodings for the response.
HTTP_ACCEPT_LANGUAGE
– Acceptable languages for the response.
HTTP_HOST
– The HTTP Host header sent by the client.
HTTP_REFERER
– The referring page, if any.
HTTP_USER_AGENT
– The client’s user-agent string.
QUERY_STRING
– The query string, as a single (unparsed) string.
REMOTE_ADDR
– The IP address of the client.
REMOTE_HOST
– The hostname of the client.
REMOTE_USER
– The user authenticated by the Web server, if any.
REQUEST_METHOD
– A string such as "GET"
or "POST"
.
SERVER_NAME
– The hostname of the server.
SERVER_PORT
– The port of the server (as a string).
具体使用如:
1def get_headers(request): 2 print(request.META['CONTENT_TYPE']) 3 return HttpResponse('OK')
Flask和Django中request对象属性的对比
method:一个字符串,表示请求使用的HTTP方法,常用值包括:'GET'、'POST'
user:请求的用户对象。
path:一个字符串,表示请求的页面的完整路径,不包含域名和参数部分。
encoding:一个字符串,表示提交的数据的编码方式。
如果为None则表示使用浏览器的默认设置,一般为utf-8。
这个属性是可写的,可以通过修改它来修改访问表单数据使用的编码,接下来对属性的任何访问将使用新的encoding值。
FILES:一个类似于字典的对象,包含所有的上传文件。
6.3响应response
视图可以返回HttpResponse
类的对象或者子类的对象
构造响应对象的时候:
content_type
默认是text/html
status
默认是200
响应对象的子对象不需要记忆,下面的方式可以查找
from django.http import HttpResponse
中的http可以点进去查看源代码,或者HTTPResponse
中查看源代码
构造对象的时候,设置对象属性,两种方式:
1from django.http import HttpResponse 2 3def demo_view(request): 4 return HttpResponse('itcast python', status=400) 5 或者 6 response = HttpResponse('itcast python') 7 response.status_code = 400 8 response['Itcast'] = 'Python' 9 return response
6.3.1响应时返回json数据
Flask中:jsonify
Django中:JsonResponse(<dict>)
Django中的JsonResponse(<dict>)
其实先将字典转换成json字符串,然后将响应头Content-Type设置为 application/json
6.3.2响应时进行页面的重定向
flask和Django中的重定向是一样的redirect('重定向的url地址')
6.4cookie
6.4.1对比
特点:
1、cookie数据保存在客户端,以key-value存储
2、cookie有过期的时间,默认是关闭浏览器过期
3、cookie基于域名安全的,浏览器在访问一个服务器时,只会把和跟这个服务器相关的cookie发送过去。
设置:
1flask: 2 3response = make_response(‘响应内容’) 4 5response.set_cookie('<key>','<value>',max_age='<过期时间:s>') 6 7Django: 8 9response = HttpResponse('响应内容') 10 11response.set_cookie('<key>','<value>',max_age='<过期时间:s>')
获取:
1flask中: 2 3request.cookies.get('<key>') 4 5Django中: 6 7request.COOKIES.get('<key>')
删除:
1flask和Django一样 2 3response.delete_cookie('<key>')
6.5session
6.5.1flask中session
特点:
1、session数据保存在服务器,以key-value存储
2、session依赖于cookie,每个客户端的session信息标识(sessionID)保存在哭护短cookie中
3、session也有过期时间,flask开启session过期时间之后默认是30天,Django中session过期时间默认是2周。
设置:
from flask import session
session['<key>'] = '<value>'
获取:
session.get('<key>')
6.5.2django中session
存储方式:
1、关系数据库:默认的存储方式(django_session)
SESSION_ENGINE='django.contrib.sessions.backends.db'
2、缓存:Django框架缓存默认是服务器内存
SESSION_ENGINE='django.contrib.sessions.backends.cache'
3、混合存储
SESSION_ENGINE='django.contrib.sessions.backends.cached_db'
4、将session信息存储到redis中:
1、安装扩展包:
pip install django-redis
2、配置:
在settings.py文件中做如下设置
1# 设置Django框架的存储位置(如果不做设置,缓存默认是服务器内存) 2# 此处是要把Django框架的缓存改为redis 3# 缓存里面有多个小空间,我们可以设置多个 4CACHES = { 5 "default": { 6 "BACKEND": "django_redis.cache.RedisCache", 7 # 设置redis数据库地址 8 "LOCATION": "redis://127.0.0.1:6379/1", 9 "OPTIONS": { 10 "CLIENT_CLASS": "django_redis.client.DefaultClient", 11 } 12 } 13 "session": { 14 "BACKEND": "django_redis.cache.RedisCache", 15 # 设置redis数据库地址 16 "LOCATION": "redis://127.0.0.1:6379/1", 17 "OPTIONS": { 18 "CLIENT_CLASS": "django_redis.client.DefaultClient", 19 } 20 } 21} 22# 设置将Django框架的session存储到缓存中,上面已经将Django中的缓存改为了redis,所以session存储到了redis中 23SESSION_ENGINE = "django.contrib.sessions.backends.cache" 24# 设置session存储到缓存空间的名称 25SESSION_CACHE_ALIAS = "default"
3、设置session:
request.session['<key>']='<value>'
·
4、获取session:
request.session.get('<key>')
注意:
Django中默认是开启session的
框架会根据cookie中的sessionid到redis数据库中取到值,然后放到request.session
中,我们就可以取到了。