当用户第一次访问网站时,网站的服务器将自动创建一个Session对象,该Session对象相当于该用户在网站的一个身份凭证,而且Session能存储该用户的数据信息。当用户在网站的页面之间跳转时,存储在Session对象中的数据不会丢失,只有Session过期或被清理时,服务器才将Session中存储的数据清空,并终止该Session.
当获取某用户的Session数据时,首先从用户传递的Cookie里获取sessionid,然后根据sessionid在网站服务器找到相应的Session。
Session存放在服务器的内存中,因此存放在Session中的数据不能过于庞大。
每个用户的Session通过Django的中间件MIDDLEWARE接收和调度处理
django.contrib.sessions.middleware.SessionMiddleware
当访问网站时,所有的HTTP请求都经过中间件处理,中间件SessionMiddleware
相当于HTTP请求接收器,根据请求信息做出相应的调度,而程序的执行则由settings.py的配置属性INSTALLED_APPS中django.contrib.sessions
完成。
django.contrib.sessions实现了Session的创建和操作处理,如创建或存储用户的Session对象,管理Session的生命周期等,它默认使用数据库存储Session信息,数据库名为django_session
Session默认存储在数据库中,变更的话可在settings.py中添加配置信息SESSION_ENGINE,该配置可以指定Session的保存方式。
django提供5种Session的保存方式
# 数据库存储方式,django默认,无需再settings.py中设置 SESSION_ENGINE = 'django.contrib.sessions.backends.db' # 以文件形式保存 SESSION_ENGINE = 'django.contrib.sessions.backends.file' # 使用文本保存可设置文件保存路径,有相对路径和绝对路径 SESSION_FILE_PATH = '/MyDjango' # /MyDjango代表文本保存在项目MyDjango的根目录 # 以缓存形式保存 SESSION_ENGINE = 'django.contrib.sessions.backends.cache' # 设置缓存名,默认是内存缓存方式,此处的设置与缓存机制的设置有关 SESSION_CACHE_ALIAS = 'default' # 以数据库+缓存形式保存 SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db' # 以Cookie形式保存 SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'
也是通过服务器后端的Session设置的
比如Cookie的生命周期,传输方式或保存路径等
待补
Session的数据类型可理解为Python的字典类型,主要在视图函数中进行读写,从用户请求中获取(来自视图函数的request)
待补
他的会话存储实现两个页面事件的数据传递,这个我并未弄清楚
笔记待补
当网站访问过大时,网站的响应速度必然大大降低,知识和可以在网站上使用缓存机制。
缓存是将一个请求的响应内容保存到内存、数据库、文件或者高速缓存系统(Memcache)中,若某个事件再次接收同一个请求,则不再执行该请求的响应过程,而是直接从内存或者高速缓存系统中获取该请求的响应内容返回给用户。
django提供5种不同的缓存方式
待补
每种缓存方式都需结合网站的实际情况而定。若在项目中使用缓存机制,则首先在配置文件settings.py中设置缓存的相关配置.
# 每种缓存方式的配置
缓存配置的参数BACKEND和LOCATION是必选参数,其余的配置参数可自行选择。
完整的数据库缓存配置
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', } }
DJango允许同时配置和使用多种不同类型的缓存方式,配置方法与多数据库的配置方式类似。缓存数据表的创建依赖于数据库配置settings.py中的DATABASES,如果有多个数据库,则默认在DATABASES的default的数据库中生成。
缓存的使用方式有4种,主要根据不同的适用对象进行划分。
全站缓存 视图缓存 路由缓存 模板缓存
全站缓存在django的中间件中配置,
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' # 指定某个站点的名称
在视图函数或视图类的执行过程中生成缓存数据,视图使用装饰器生成,并保存缓存数据。
装饰器设有参数timeout,cache,key_prefix,参数timeout是必选参数,其余两个参数是可选参数。参数的作用与全局缓存的配置属性相同
from django.shortcuts import render # 导入cache_page 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') def index(request): return render(request, 'index.html')
在路由文件urls.py中生成和保存的,路由缓存也是使用缓存函数cache_page实现的。
from django.views.decorators.cache import cache_page urlpatterns = [ # 网站首页设置路由缓存 path('', cache_page(timeout=10, cache='MyDjango', key_prefix='MyURL')(views.index), name='index'), # path('', views.index, name='index'), ]
模板缓存是通过Django的缓存标签实现的,缓存标签可以设置缓存的生命周期、缓存的关键词和缓存数据表(函数cache_page的参数timeout、key_prefix和cache),三者的设置顺序和代码格式是固定不变的。
<div> {# 设置模版缓存 #} {% load cache %} {# 10代表生命周期 #} {# MyTemp代表缓存数据的cache_key字段 #} {# using="MyDjango"代表缓存数据表 #} {% cache 10 MyTemp using="MyDjango" %} <div>Hello Django</div> {# 缓存结束 #} {% endcache %} </div>
CSRF防护只适用于POST请求,并不防护GET请求,因为GET请求是以只读形式访问网站资源的,一般情况下不会破坏和篡改网络数据。
防护是采用模板语法{% csrf_token %}生成一个隐藏的控件
<input type="hidden" name="csrfmiddlewaretoken" value="zUJfhT41OyX80zCqbbytV4Lc5hoQgATmg5wTeh4XnpnBrbaSytkvw0WUcNC0Dtfd">
隐藏控件的属性value值实用Django随机生成的,当用户提交表单时,django会校验表单的csrfmiddlewaretoken是否于自己保存的csrfmiddlewardtoken一致,用户每次提交表单时,隐藏控件的属性value都会随之变化。
删除模板文件的{% csrf_token %},并且在对应的视图函数中添加装饰器@csrf_exempt
from django.views.decorators.csrf import csrf_protect from django.views.decorators.csrf import csrf_exempt # 添加CSRF防护 # @csrf_protect # 取消CSRF防护 @csrf_exempt def index(request): return render(request, 'index.html')
若并未在对应视图函数中添加装饰器@csrf_exempt
,那么用户在提交表单时,程序会因CSRF验证失败而抛出403异常的页面。
若想全面取消整个网站的CSRF防护,那么可以在settings.py中MIDDLEWARE注释掉
django.middleware.csrf.CsrfViewMiddleware
但若想在某些请求上设置CSRF防护,在对应的html文件中加入{% csrf_token %},并在对应的视图函数中添加装饰器@csrf_protect
@csrf_protect def index(request): return render(request, 'index.html')
如果网页表单时使用前端的Ajax向Django提交表单数据的,Django设置了CSRF防护功能,Ajax发送POST请求就必须设置请求参数csrfiddlewaretoken,否则Django会将当前请求视为恶意请求。Ajax发送POST的请求的功能代码如下
待补(很重要)
在网页应用中,当用户完成某个功能操作时,网站会有相应的消息提示。Django内置的消息框架可以供开发者直接调用,它允许开发者设置功能引擎、消息类型和消息类容。
消息框架由中间件SessionMiddleware,MessageMiddleware和INSTALLED_APPS中的django.contrib.sessions,django.contrib.messages共同实现。
MessageMiddleware(essionMiddleware,,是哪一个中间件)的功能引擎默认使用FallbackStorage,而FallbackStorage是在session的基础上实现的,所以SessionMiddleware中间件必须设置在MessageMiddleware前面。
相关资料展现的有些许不同
MessageMiddleware的源码位置
待补
MessageMiddleware源码文件所包含的文件及作用
待补
消息框架主要在视图和模板中使用,而且消息框架在视图函数和视图类有着不一样的使用方式
# MESSAGE_STORAGE = 'django.contrib.messages.storage.cookie.CookieStorage' # MESSAGE_STORAGE = 'django.contrib.messages.storage.session.SessionStorage' # FallbackStorage是默认使用,可以无需设置 MESSAGE_STORAGE = 'django.contrib.messages.storage.fallback.FallbackStorage'
设置url
待补
定义对应的视图函数
这里有个上下文处理器,值得注意
待补
分页功能需要考虑的因素:
1.当前用户访问的页数是否存在上(下)页
2.访问的页数是否超出页数上限
3.数据如何按页截取,如何设置每页的数据量
主要实现分页的Paginator类一共定义了4个初始化参数和8个类方法,每个初始化参数和类方法的说明如下
待补
我们将Paginator实例化之后,在由实例化对象调用get_page()即可得到Page类的实例化对象。在源码文件paginator.py中可以找到Page类的定义过程,它一共定义了3个初始化参数和7个类方法
待补
使用django的shell模式,简述使用分页功能
In [1]: # 导入分页功能模块 In [2]: from django.core.paginator import Paginator In [3]: # 生成数据列表 In [4]: objects = [chr(x) for x in range(97,107)] In [5]: objects Out[5]: ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'] In [6]: # 将数据列表以每3个元素分页 In [7]: p = Paginator(objects,3) In [8]: # 输出全部数据,即整个数据列表 In [9]: p.object_list Out[9]: ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'] In [10]: # 获取数据列表长度 In [11]: p.count Out[11]: 10 In [12]: 分页后的总页数 --------------------------------------------------------------------------- NameError Traceback (most recent call last) <ipython-input-12-b9a482fe307d> in <module> ----> 1 分页后的总页数 NameError: name '分页后的总页数' is not defined In [13]: # 分页后的总页数 In [14]: p.num_pages Out[14]: 4 In [15]: # 将页数转换为range循环对象 In [16]: p.page_range Out[16]: range(1, 5) In [17]: # 获取第二页的数据信息 In [18]: page2 = p.get_page(2) In [19]: # 判断第二页上是否还有上一页 In [20]: page2.has_previous() Out[20]: True In [21]: # 判断第二页是否存在下一页 In [22]: page2.has_next() Out[22]: True In [23]: # 如果当前页存在下一页,就输出下一页的页数 In [24]: # 否则抛出EmptyPage异常 In [25]: page2.next_page_number() Out[25]: 3 In [26]: # 如果当前页存在上一页,就输出上一页的页数 In [27]: # 否则抛出EmptyPage异常 In [28]: page2.previous_page_number() Out[28]: 1 In [29]: # 判断当前页是否存在上一页或者下一页 In [30]: page2.has_other_pages() Out[30]: True In [31]: # 输出第二页所对应的数据内容 In [32]: page2.has_other_pages() Out[32]: True In [33]: page2.object_list Out[33]: ['d', 'e', 'f'] In [34]: # 输出第二页的第一行数据在整个数据列表的位置 In [35]: # 数据位置从1开始计算 In [36]: page2.start_index() Out[36]: 4 In [37]: # 输出第二页的最后一行数据在整个数据列表的位置 In [38]: # 数据位置从1开始计算 In [39]: page2.end_index() Out[39]: 6
diango分页功能的具体使用,主要在views.py中的视图函数中使用,一般需要在视图函数中传入自定义参数来当个page变量实例化,作用在模板文件上
待补