更新了Django第5天和第6天的文档

pull/166/head
jackfrued 2019-05-26 00:51:21 +08:00
parent 5bd10ce64e
commit e18721d8b4
5 changed files with 107 additions and 1 deletions

BIN
.DS_Store vendored

Binary file not shown.

View File

@ -135,3 +135,51 @@ SESSION_ENGINE = 'django.contrib.sessions.backends.cache'
SESSION_CACHE_ALIAS = 'default' SESSION_CACHE_ALIAS = 'default'
``` ```
如果要修改session数据默认的序列化方式可以将默认的`JSONSerializer`修改为`PickleSerializer`。
```Python
SESSION_SERIALIZER = 'django.contrib.sessions.serializers.PickleSerializer'
```
### 在视图函数中读写cookie
Django封装的`HttpRequest`和`HttpResponse`对象分别提供了读写cookie的操作。
HttpRequest封装的属性和方法
1. `COOKIES`属性 - 该属性包含了HTTP请求携带的所有cookie。
2. `get_signed_cookie`方法 - 获取带签名的cookie如果签名验证失败会产生`BadSignature`异常。
HttpResponse封装的方法
1. `set_cookie`方法 - 该方法可以设置一组键值对并将其最终将写入浏览器。
2. `set_signed_cookie`方法 - 跟上面的方法作用相似但是会对cookie进行签名来达到防篡改的作用。因为如果篡改了cookie中的数据在不知道[密钥](<https://zh.wikipedia.org/wiki/%E5%AF%86%E9%92%A5>)和[盐](<https://zh.wikipedia.org/wiki/%E7%9B%90_(%E5%AF%86%E7%A0%81%E5%AD%A6)>)的情况下是无法生成有效的签名这样服务器在读取cookie时会发现数据与签名不一致从而产生`BadSignature`异常。需要说明的是这里所说的密钥就是我们在Django项目配置文件中指定的`SECRET_KEY`,而盐是程序中设定的一个字符串,你愿意设定为什么都可以,只要是一个有效的字符串。
上面提到的方法如果不清楚它们的具体用法可以自己查阅一下Django的[官方文档](<https://docs.djangoproject.com/en/2.1/ref/request-response/>),没有什么资料比官方文档能够更清楚的告诉你这些方法到底如何使用。
刚才我们说过了,激活`SessionMiddleware`之后,每个`HttpRequest`对象都会绑定一个session属性它是一个类似字典的对象除了保存用户数据之外还提供了检测浏览器是否支持cookie的方法包括
1. `set_test_cookie`方法 - 设置用于测试的cookie。
2. `test_cookie_worked`方法 - 检测测试cookie是否工作。
3. `delete_test_cookie`方法 - 删除用于测试的cookie。
4. `set_expiry`方法 - 设置会话的过期时间。
5. `get_expire_age`/`get_expire_date`方法 - 获取会话的过期时间。
6. `clear_expired`方法 - 清理过期的会话。
下面是在执行登录之前检查浏览器是否支持cookie的代码。
```Python
def login(request):
if request.method == 'POST':
if request.session.test_cookie_worked():
request.session.delete_test_cookie()
# Add your code to perform login process here
else:
return HttpResponse("Please enable cookies and try again.")
request.session.set_test_cookie()
return render_to_response('login.html')
```
### Cookie的替代品
之前我们说过了cookie的名声一直都不怎么好当然我们在实际开发中是不会在cookie中保存用户的敏感信息如用户的密码、信用卡的账号等而且保存在cookie中的数据一般也会做好编码和签名的工作。即便如此HTML5中还是给出了用于替代cookie的技术方案其中使用得最为广泛的就是localStorage和sessionStorage相信从名字上你就能听出二者的差别存储在`localStorage`的数据可以长期保留;而存储在`sessionStorage`的数据会在浏览器关闭时会被清除 。关于这些cookie替代品的用法建议大家查阅[MDN](<https://developer.mozilla.org/zh-CN/docs/Web>)来进行了解。

View File

@ -1,4 +1,62 @@
## 中间件的应用 ## 中间件的应用
我们继续来完善投票应用。在上一个章节中我们在用户登录成功后通过session保留了用户信息接下来我们可以应用做一些调整要求在为老师投票时必须要先登录登录过的用户可以投票否则就将用户引导到登录页面为此我们可以这样修改视图函数。
```Python
def praise_or_criticize(request: HttpRequest):
"""投票"""
if 'user' in request.session:
try:
tno = int(request.GET.get('tno', '0'))
teacher = Teacher.objects.get(no=tno)
if request.path.startswith('/vote/praise'):
teacher.good_count += 1
else:
teacher.bad_count += 1
teacher.save()
data = {'code': 200, 'message': '操作成功'}
except (ValueError, Teacher.DoesNotExist):
data = {'code': 404, 'message': '操作失败'}
else:
data = {'code': 401, 'message': '请先登录'}
return JsonResponse(data)
```
前端页面在收到`{'code': 401, 'message': '请先登录'}`后,可以将用户引导到登录页面。
```HTML
<script>
$(() => {
$('.comment > a').on('click', (evt) => {
evt.preventDefault()
let a = $(evt.target)
$.ajax({
url: a.attr('href'),
type: 'get',
dataType: 'json',
success: (json) => {
if (json.code == 200) {
let span = a.next()
span.text(parseInt(span.text()) + 1)
} else if (json.code == 401) {
location.href = '/vote/login/?backurl=' + location.href
} else {
alert(json.message)
}
}
})
})
})
</script>
```
> 注意:为了在登录成功之后能够回到刚才投票的页面,我们在跳转登录时设置了一个`backurl`参数把当前浏览器中的URL作为返回的页面地址。
这样我们已经实现了用户必须登录才能投票的限制但是一个新的问题来了。如果我们的应用中有很多功能都需要用户先登录才能执行那么我们是不是需要在每个视图函数中添加代码来检查session中是否包含了登录用户的信息呢答案是否定的如果这样做了我们的视图函数中必然会充斥着大量的重复代码。编程大师Martin Fowler曾经说过**代码有很多种坏味道,重复是最坏的一种**。我们可以把验证用户是否登录这样的代码放到Django的中间件中。
### Django中间件概述
### 自定义中间件

View File

@ -256,7 +256,7 @@
- 实现用户跟踪 - 实现用户跟踪
- cookie和session的关系 - cookie和session的关系
- Django框架对session的支持 - Django框架对session的支持
- 视图函数中实现cookie读写 - 视图函数中的cookie读写操作
#### Day46 - [中间件的应用](./Day41-55/06.中间件的应用.md) #### Day46 - [中间件的应用](./Day41-55/06.中间件的应用.md)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB