1.会话控制Session
Session和cookie的关系:Session存储在服务器端,cookie存储在客户端
使用会话实现商品抢购
#index models.py
from django.db import models
# Create your models here.
class Product(models.Model):
id = models.AutoField('序号',primary_key = True)
name = models.CharField('名称',max_length=50)
slogan = models.CharField('简介',max_length=50)
sell = models.CharField('宣传',max_length=50)
price = models.IntegerField('价格')
photo = models.CharField('相片',max_length=50)
def __str__(self):
return self.name
#views.py
from django.contrib.auth.decorators import login_required
# Create your views here.
from django.shortcuts import redirect, render
from index.models import Product
@login_required(login_url = 'admin/login')
def index(request):
id = request.GET.get('id','')
if id:
idList = request.session.get('idList',[])
if not id in idList:
idList.append(id)
request.session['idList'] = idList
return redirect('/')
products = Product.objects.all()
return render(request,'index.html',locals())
def orderView(request):
idList = request.session.get('idList',[])
del_id = request.GET.get('id','')
if del_id in idList:
idList.remove(del_id)
request.session['idList'] = idList
products = Product.objects.filter(id__in=idList)
return render(request,'order.html',locals())
两个页面之间的数据转化由Session实现:
- 商城首页实现Session的读取和写入。首先获取Session的idList,如果当前请求存在参数id,就判断Session的idList是否存在参数请求的id值,若不存在,则将id的值写入idList。
- 订单信息页实现Session的读取和删除。首先获取Session的idList,如果当前请求存在请求参数id,就判断Session的idList是否存在请求参数id,若存在,则从Session的idList删除请求参数id的值。
2. 缓存机制
Django 5种缓存方式:
- Memcached:一个高性能的分布式内存对象缓存系统,用于动态网站,以减轻数据库负载。适合超大型网站使用。
- 数据库缓存:缓存信息存储在网站数据库的缓存列表中,缓存表可以在项目的配置文件中配置,适合大中型网站使用。
- 文件系统缓存:缓存信息以文本文件格式保存,适合中小型网站使用。
- 本地内存缓存:Django默认的缓存保存方式,将缓存存放在计算机的内存中,只适用于项目的开发测试。
- 虚拟缓存:Django内置的虚拟缓存,实际上只提供缓存接口,不能缓存数据,只适用于项目开发测试。
以数据库缓存为例,配置如下:
CACHES = {
# 默认缓存数据表
'default': {
'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
'LOCATION': 'my_cache_table',
# TIMEOUT设置缓存的生命周期,以秒为单位,若为None,则永不过期
'TIMEOUT': 60,
'OPTIONS': {
# MAX_ENTRIES代表最大缓存记录的数量
'MAX_ENTRIES': 1000,
# 当缓存到达最大数量之后,设置剔除缓存的数量
'CULL_FREQUENCY': 3,
}
},
# 设置多个缓存数据表
'MyDjango': {
'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
'LOCATION': 'MyDjango_cache_table',
}
}
缓存的4种使用:
- 全站缓存:将缓存作用于整个网站的全部页面。一般情况下不采用这种方式。
- 视图缓存:当用户发送请求时,若该请求的视图函数已经生成缓存数据,则以缓存数据作为响应内容,可省去视图函数处理请求的时间和资源。
- 路由函数:作用与视图函数相同,不同在于当两个路由指向同一个视图函数,分别访问两个路由地址时,路由缓存会判断路由地址是否已经生成缓存从而决定是否执行视图函数。
- 模板缓存:对模板某部分的数据设置缓存,常用于模板内容变动较少的情况。
全站缓存的例子:
MIDDLEWARE = [
# 配置全站缓存
# 'django.middleware.cache.UpdateCacheMiddleware',
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
# 使用中文
'django.middleware.locale.LocaleMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
# 配置全站缓存
'django.middleware.cache.FetchFromCacheMiddleware',
]
# 设置缓存的生命周期
CACHE_MIDDLEWARE_SECONDS = 15
# 设置缓存数据保存在数据表my_cache_table中
# 属性值default来自于缓存配置CACHES的default属性
CACHE_MIDDLEWARE_ALIAS = 'default'
# 设置缓存表字段cache_key的值
# 用于同一个Django项目多个站点之间的共享缓存
CACHE_MIDDLEWARE_KEY_PREFIX = 'MyDjango'
视图缓存例子:
from django.views.decorators.cache import cache_page
参数cache与配置属性CACHE_MIDDLEWARE_ALIAS相同
参数key_prefix与配置属性CACHE_MIDDLEWARE_KEY_PREFIX相同
参数timeout与配置属性CACHE_MIDDLEWARE_SECONDS相同
CACHE_MIDDLEWARE_SECONDS的优先级高于参数timeout
@cache_page(timeout=10, cache='MyDjango', key_prefix='MyView')
路由缓存:
urlpatterns = [
网站首页设置路由缓存
path('', cache_page(timeout=10, cache='MyDjango', key_prefix='MyURL')(views.index), name='index'),
path('', views.index, name='index'),
]
模板缓存:
<html>
<body>
<div>
{# 设置模版缓存 #}
{% load cache %}
{# 10代表生命周期 #}
{# MyTemp代表缓存数据的cache_key字段 #}
{# using="MyDjango"代表缓存数据表 #}
{% cache 10 MyTemp using="MyDjango" %}
<div>Hello Django</div>
{# 缓存结束 #}
{% endcache %}
</div>
</body>
</html>
3.CSRF防护
CSRF(Cross-Site Request Forgery,跨站请求伪造)一种对网站的恶意利用,窃取网站的用户信息来制造恶意请求。
在中间件中设置CSRF防护功能,在模板文件的表单标签中加入{%csrf_token%},想取消表单的CSRF,在相应的视图函数中添加@csrf_exempt
4.消息框架
完成某个功能造作时,网站会有相应的消息提示。
消息框架是由中间件SessionMiddleware、MessageMiddleware、INSTALLED_APPS的django.contrib.messages和django.contrib.session共同实现。一共定义了5种消息类型:
类型 | 级别 | 说明 |
---|---|---|
DEBUG | 10 | 开发过程的调试信息,但运行时无法生成信息 |
INFO | 20 | 提示信息,如用户信息 |
SUCCESS | 25 | 提示当前操作执行成功 |
WARNING | 30 | 警告当前操作存在风险 |
ERROR | 40 | 提示当前操作错误 |
5.分页功能
调用Paginator函数
def index(request, page):
# 获取模型PersonInfo的全部数据
person = PersonInfo.objects.all().order_by('-age')
# 设置每一页的数据量为2
p = Paginator(person, 2, 1)
try:
pages = p.get_page(page)
except PageNotAnInteger:
# 如果参数page的数据类型不是整型,就返回第一页数据
pages = p.get_page(1)
except EmptyPage:
# 若用户访问的页数大于实际页数,则返回最后一页的数据
pages = p.get_page(p.num_pages)
return render(request, 'index.html', locals())
6.国际化和本地化
1.Django的国际化和本地化时默认开启的,在配置文件中USE——I18N配置,需要依赖GNUGettext工具。
2.安装GNUGettext成功后,在根目录下黄健文件夹language,配置文件中添加在中间件LocaleMiddleware,新增配置属性LOCALE_PATHS和LANGUAGES
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.middleware.common.CommonMiddleware',
...
]
LOCALE_PATHS = (
os.path.join(BASE_DIR, 'language'),
)
LANGUAGES = (
('en', ('English')),
('zh', ('中文简体')),
)
3.在路由、视图、模板里使用国际化设置
#MyDjango urls.py
urlpatterns = i18n_patterns(
path('', include(('index.urls', 'index'), namespace='index')),
)
#APP urls.py
urlpatterns = [
path('', index, name='index'),
]
#views.py
from django.shortcuts import render
from django.utils.translation import gettext
from django.utils.translation import gettext_lazy
def index(request):
if request.LANGUAGE_CODE == 'zh':
language = gettext('Chinese')
# language = gettext_lazy('Chinese')
else:
language = gettext('English')
# language = gettext_lazy('English')
print(language)
return render(request, 'index.html', locals())
#模板文件
<!DOCTYPE html>
<html>
<head>
{% load i18n %}
<title>{% trans "Choice language" %}</title>
</head>
<body>
<div>
{#将配置属性LANGUAGES进行列举,显示网站支持的语言#}
{% get_available_languages as languages %}
{% trans "Choice language" %}
{% for lang_code, lang_name in languages %}
{% language lang_code %}
<a href="{% url 'index:index'%}">{{ lang_name }}</a>
{% endlanguage %}
{% endfor %}
</div>
<br>
<div>
{% blocktrans %}
The language is {{ language }}
{% endblocktrans %}
</div>
</body>
</html>
4.执行本地化操作,命令行执行python manage.py makemessages -1 zh 出现异常,早language问价减重设置编写翻译内容
#: .\index\views.py:7
msgid "Chinese"
msgstr "简体中文"
#: .\index\views.py:10
msgid "English"
msgstr "English"
#: .\templates\index.html:5 .\templates\index.html:11
msgid "Choice language"
msgstr "请选择语言:"
#: .\templates\index.html:20
#, python-format
msgid ""
"\n"
" The language is %(language)s\n"
msgstr ""
"\n"
" 当前语言为: %(language)s\n"
5.以管理员身份运行命令行,执行python manage.py compilemessages
7.单元测试
在test.py中继承TestCase编写测试用例
8.自定义中间件
一个完整的中间件设有5个钩子函数,Django将用户请求到网站响应的过程进行划分,每个阶段对应执行某个钩子函数。
- inti():初始化函数,运行Django将自动执行该函数。
- process_request():完成请求对象的创建,但用户访问的网址尚未与网站的路有四只匹配。
- process_view():完成用户访问的网址与路由地址的匹配,但尚未执行视图函数。
- process_exception():在执行视图函数的期间发生异常,比如代码异常、主动抛出404异常等。
- process_response():完成视图函数的执行,但尚未将响应内容返回浏览器。
实现Cookie反爬虫
#myMiddwear.py
from django.utils.deprecation import MiddlewareMixin
from django.utils.timezone import now
from django.shortcuts import Http404
class MyMiddleware(MiddlewareMixin):
def process_view(self, request, func, args, kwargs):
if func.__name__ != 'index':
salt = request.COOKIES.get('value', '')
try:
request.get_signed_cookie('MySign', salt=salt)
except Exception as e:
print(e)
raise Http404('当前Cookie无效哦!')
def process_response(self, request, response):
salt = str(now())
response.set_signed_cookie(
'MySign',
'sign',
salt=salt,
max_age=10
)
response.set_cookie('value', salt)
return response