一、视图概述
Django用视图
这个概念封装处理用户请求并返回响应的逻辑。
定义视图函数相关的URL(网址) (即规定 访问什么网址对应什么内容)。或者说视图接受Web请求,并响应Web请求。
视图的本质就是一个python函数.
- 概念
- 响应
网页(包含重定向、错误视图404、错误视图500、错误视图400)
JSON数据
- 过程
用户在浏览器中输入网址www.zyz.com/meituan/detail.html
django获取到网址信息,截取掉IP和端口 meituan/detail.html
对应虚拟路径和文件名,在url管理器中逐个匹配urlconf列表 detail
调用视图管理器中的detail,返回对应结果给浏览器
- 定义视图
from django.http import HttpResponse
# 没有使用任何的模板
def index(request):
return HttpResponse('hello zyz!!!')
- 配置url (简单)
# 修改project/urls.py文件
from django.conf.urls import url,include
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^', include('myapp.urls', namespace='app')), # 会定位到myapp.urls中
]
# 在对应应用中appname中,创建urls.py文件(与上面文件类似)
from django.conf.urls import url
from . import views # 导入视图
urlpatterns = [
url(r'^$', views.index, name='index') # 匹配到的就是views中的首页
]
- 配置url (带参数)
# 描述(在views.py中定义的视图)
def detail(request,num):
return HttpResponse('detail-%s' % num)
# 在appname/urls.py中配置即可
urlpatterns = [
url(r'^$', views.index),
# 添加括号,其实就是正则表达式中的组的概念。
# 而匹配到的就是可以给到 detail(request,num) 函数中的num
url(r'^(\d+)/$', views.detail)
]
二、URL配置
- 配置流程
- URL配置文件
settings.py文件中ROOT_URLCONF=project.urls (默认已经配置好)
- project.urls.py文件
urlpatterns是一个url实例列表
url对象(正则表达式,视图名称,名称)
例如: url(r'^admin/', admin.site.urls,name='admin')
- url匹配正则注意事项
想要从url中获取一个值,需要对正则加小括号(即分组)
匹配正则前方不需要加反斜杠
正则前面需要加r表示字符串不转义
- 引入其他配置
- 在应用中创建urls.py文件,配置该应用内的路由
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.index, name='index'),
url(r'^(\d+)/$', views.detail, name='detail'),
]
- 在工程目录中urls.py分发到对应应用中
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^app/', include('myapp.urls', namespace='app')),
]
- 反向解析
- 概述: 如果在视图、模板中使用了硬编码链接,在url配置发生改变时,动态生成链接地址
- 解决: 在使用链接时,通过url配置的名称,动态生成url地址
- 作用: 使用url模板或试图中
模板中: {% url 'namespace:name' value1 value2 ...%}
视图中: redirect('namespace:name', arg1, arg2...)
三、视图函数
- 定义视图
- 本质: 视图即是一个函数
- 参数: 一个HttpRequest对象,通过正则表达式获取的参数
- 位置: 一般会在views.py中定义
- 错误视图
- 404视图
找不到网页时返回(url匹配不成功)
在temmplates目录下定义404.html({{request_path}}会输出导致错误的网址)
配置settings.py(DEBUG如果为True永远不会调用404.html页面)
配置settings.py(ALLOWED_HOSTS=['*'])
- 505视图
视图代码出现错误(服务器错误)
- 400视图
错误出现在客户的操作
四、HttpRequest对象
- 概述
- 服务器接收http请求后,会根据报文创建HttpRequest对象
- 视图的第一个参数就是HttpRequest对象
- django创建的,之后调用视图时传递给视图
- 属性
- path
请求的完整路径(不包括域名和端口)
- method
请求的方式,常用有GET、POST
- encoding
浏览器提交数据的编码方式
- GET [GET请求参数]
类似字典对象,包含get请求的所有参数
- POST [POST请求参数]
类似字典对象,包含post请求的所有参数
- FILES
类似字典对象,包含所有上传的文件
- COOKIES
字典,包含所有的cookie
- session
类似字典对象,表示当前会话
- 方法
- is_ajax()
通过XMLHttpRequest发起的,就会返回True
- QueryDict对象
- request对象中的GET、POST都属于QueryDict对象
- get()
根据键获取值(只能获取一个)
也可以通过方括号的方式获取数据(如果不存在会报错)
- getlist()
根据键获取值(返回的是一个列表,可以获取多个值)
- GET属性
- 获取浏览器传递给服务器的数据
- 例如: http://127.0.0.1:8000/zyz/get1?a=1&b=2&c=3
def get1(request):
a = request.GET.get('a')
b = request.GET['b']
c = request.GET.get('c')
return HttpResponse('a:%s b:%s c:%s' % (a,b,c))
- 例如: http://127.0.0.1:8000/zyz/get2?a=1&a=2&b=3
def get2(request):
a = request.GET.getlist('a')
a1 = a[0]
a2 = a[1]
b = request.GET['b']
return HttpResponse('a1:%s a2:%s b:%s' % (a1, a2, b))
GET请求,请求的数据会添加到URL之后,以?分割URL和传输数据,多个参数用&连接;
- POST属性
def register(request):
# 例如在输入框中对应name属性
name = request.POST['user']
passwd = request.POST.get('passwd')
tel = request.POST.get('tel')
return HttpResponse('注册成功,%s正在登录中....' % (name))
使用表单提交post请求时,需要关闭csrf(
settings.py
中的MIDDLEWARE
内的'django.middleware.csrf.CsrfViewMiddleware',
)
POST请求: 请求的数据放置在是HTTP的请求体中;
什么是 HTTP
超文本传输协议(HTTP)的设计目的是保证客户机与服务器之间的通信。
HTTP 的工作方式是客户机与服务器之间的请求-应答协议。
客户端(浏览器)向服务器提交 HTTP 请求;服务器向客户端返回响应。HTTP请求方法
1 GET 请求指定的页面信息,并返回实体主体。
2 HEAD 类似于get请求,只不过返回的响应中没有具体的内容,用于获取报头
3 POST 向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的建立和/或已有资源的修改。
4 PUT 从客户端向服务器传送的数据取代指定的文档的内容。
5 DELETE 请求服务器删除指定的页面。
6 CONNECT HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。
7 OPTIONS 允许客户端查看服务器的性能。
8 TRACE 回显服务器收到的请求,主要用于测试或诊断。
- GET和POST请求
- get一般是从服务器上获取数据,post一般是向服务器传送数据;
- get传送的数据量较小,不能大于2KB。post传送的数据量较大,一般被默认为不受限制;
- get安全性非常低,post安全性较高();
如果没有加密,他们安全级别都是一样的,随便一个监听器都可以把所有的数据监听到(即也没有所谓的安全性高低问题);
五、HttpResponse对象
- 概述
- 用于给浏览器返回数据
- HttpRequest对象是django创建的,HttpResponse对象是自己创建的
response = HttpResponse()
- 返回操作
- 不调用模板(HttpResponse)
def index(request):
return HttpResponse('hello zyz!!!')
- 调用模板(render)
原型: render(request,templateName,[context...])
作用: 结合数据和模板,返回完整的HTML页面
参数: request(请求体对象)、templateName(模板路径)、context(传递给模板的数据)
例如: return render(request,'myapp/students.html',{'students':studentList})
- 属性
- content
返回的内容
- charset
返回的编码类型
- status
返回的状态码(200/304/404)
- content-type
指定输出的MIME类型
- 方法
- init
使用页面内容实例化HttpResponse对象
- write(content)
以文件的形式写入
- flush()
以文件的形式输出缓冲区
- set_cookie(key,value)
设置cookie
- delete_cookie(key)
删除cookie
删除一个不存在的key,就当什么都没发生
- 子类HttpResponseRedirect
- 作用
重定向,服务器端的跳转
- 简写
return HttpResponseRedirect('/redirect2')
from django.shortcuts import redirect
return redirect('/redirect2')
反向解析不带参数: return redirect('meituan:detail')
反向解析带参数: return redirect('meituan:detail', 10, 5)
- 子类JsonResponse
返回json数据,一般用于异步请求
def jsonrequest(request):
stu = {
'name':'zhangsan',
'score':90,
'age':20
}
return JsonResponse(stu)
Content-type类型: application/json
六、会话技术之cookie
- 概述
- http协议是无状态的,每次请求都是一次新的请求,不会保持之前的请求状态
- 客户端与服务器的一次通信就是一次回话
- 实现状态保持,在客户端或服务器存储有关回话数据
- 存储方式
cookie: 所有数据存储在客户端(不要存储敏感的数据)
session: 所有数据存储在服务端(在客户端用cookie存储session_id)
- 状态保持的目的
在一段时间内跟踪请求者的状态,可以实现跨页面访问当前的请求者数据
会话技术,其实也就是为了状态的保持,延长请求的生命周期。
- cookie概述
cookie 客户端的会话技术(数据存储在客户端);
cookie 本身由浏览器生成,通过Response将cookie写到浏览器上,下次访问,浏览器会根据不同的规则携带cookie过来;
- cookie使用
- 创建响应
response = HttpResponse()
- 设置cookie
response.set_cookie(key,value)
- 获取cookie
request.COOKIE.get(key, defaultvalue=None)
- 删除cookie
response.delete_cookie(key)
- 支持过期时间
默认: 关闭浏览器即cookie自动清除(Django)
response.set_cookie(key,value,max_age=None,expires=None)
max_age: 整数,指定cookie过期时间(单位秒)
expires: 整数,指定过期时间,还支持datetime或timedelta指定具体时间
max_age和expires两个选一个指定
max_age=0 浏览器关闭失效
max_age=Node 永不过期
max_age=Int数值 指定过期时间(单位秒)
expires 过期时间,和max_age基本一致,多一个时间差
例如: expires=timedelta(days=10) 10天后过期
例如: expires=timedelta(minutes=1) 1分钟
cookie不能跨浏览器!
- cookie使用场景
用户系统状态、购物车(京东的)...
七、会话技术之session
- session概述
session 服务端的会话技术;
session 依赖于cookie;
将session在数据库中的session_key当做sessionid存储在cookie中;
在Django中数据被存储在数据库中,并做了数据安全,使用base64进行编码;
- 启用session
在settings文件中(默认是已经启用)
INSTALLED_APPS: 'django.contrib.sessions',
MIDDLEWARE: 'django.contrib.sessions.middleware.SessionMiddleware',
- 使用session
启用session后,每个HttpRequest对象中都会有session属性(类似字典的对象)
- 设置session
request.session[key] = value
- 获取session
request.session.get(key, defaultvalue=None)
- 清除当前会话
response.delete_cookie('sessionid')
del request.session[key]
- 同时清除cookie 和 session
request.session.flush()
要注意浏览器中会有缓存问题!
- 设置过期时间
set_expiry(value)
value是整数(秒数): request.session.set_expiry(10)
value是时间对象
value是0: 关闭浏览器时失效
value是None: 永不过期
默认有效时间为两周
- 存储session的位置
- 数据库
默认存储在数据库中,在settings.py中添加
SESSION_ENGINE = 'django.contrib.sessions.backends.db'
- 缓存
只存储在本地内容中,如果丢失不能找回,但速度会比在数据库中快
SESSION_ENGINE = django.contrib.sessions.backends.cache'
- 数据库和缓存
有限从本地缓存中读取,读取不到再去数据库中获取
SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db'
- 使用redis缓存session
- 安装redis: pip3 install django-redis-sessions
- 在settings.py中添加
# redis服务相关信息
SESSION_ENGINE = 'redis_sessions.session'
SESSION_REDIS_HOST = 'localhost'
SESSION_REDIS_PORT = 6379
SESSION_REDIS_DB = 0 # 选择数据库
SESSION_REDIS_PASSWORD = '123456' # 如果没有密码,则不需要
SESSION_REDIS_PREFIX = 'session' # 前缀
- 使用时还需要启动redis
redis-server
八、会话技术之token
- token概述
token 服务端会话技术;
token 实际就是手动实现session;
- token生成
# token唯一标识
# 策略1: 时间戳 + 随机数 + 公司域名 + ip信息
# 策略2: 时间戳 + 域名
# ...
def generate_token():
token = str(time.time()) + str(random.random())
# md5算法
md5 = hashlib.md5()
md5.update(token.encode('utf-8'))
token = md5.hexdigest()
return token
MD5消息摘要算法,一种被广泛使用的密码散列函数,可以产生出一个128位(16字节)的散列值(hash value),用于确保信息传输完整一致。【摘要算法、哈希算法】
- UUID
通用唯一标识符(Universally Unique Identifier), 对于所有的UUID它可以保证在空间和时间上的唯一性。
通过MAC地址, 时间戳, 命名空间, 随机数, 伪随机数来保证生成ID的唯一性。 UUID可以被用作多种用途, 既可以用来短时间内标记一个对象, 也可以可靠的辨别网络中的持久性对象。
- uuid1() 基于时间戳 【不建议使用】
由MAC地址、当前时间戳、随机数生成;
但MAC的使用同时带来安全性问题,局域网中可以使用IP来代替MAC;
例如: token = uuid.uuid1()
- uuid2() 基于分布式计算环境DCE 【Python中没有这个函数】
算法与uuid1相同,不同的是把时间戳的前4位置换为POSIX的UID;
实际中很少用到该方法;
- uuid3(namespace,name) 基于名字的MD5散列值 【推荐使用】
通过计算名字和命名空间的MD5散列值得到;
保证了同一命名空间中不同名字的唯一性和不同命名空间的唯一性;
但同一命名空间的同一名字生成相同的uuid;
例如: token = uuid.uuid3(uuid.NAMESPACE_DNS, 'test')
- uuid4() 基于随机数 【不推荐使用】
由伪随机数得到,有一定的重复概率,该概率可以计算出来;
例如: token = uuid.uuid4()
- uuid5(namespace,name) 基于名字的SHA-1散列值 【推荐使用】
算法与uuid3相同,不同的是使用 Secure Hash Algorithm 1 算法;
例如: token = uuid.uuid5(uuid.NAMESPACE_DNS, 'test')
namespace 可以是任意 uuid 字符串,例如: temp = uuid.uuid5(uuid.uuid4(), 'test')
九、数据安全
服务器的数据对任何人来说都应该是不可见的(不透明的);
可以使用常见的摘要算法对数据进行摘要(md5,sha);
如果使用了数据安全,那么就需要在所有数据验证的地方都加上 数据安全;
# 例如使用MD5
def password_set(password):
md5 = hashlib.md5()
md5.update(password.encode("utf-8"))
return md5.hexdigest()