一. Session:https://www.cnblogs.com/liwenzhou/p/8343243.htm
1. 什么要有session?Cookied的缺点:
1. 存储的最大数据量只有4096字节
2. 数据都保存在客户端(浏览器)上,不安全
2. Session的简单流程(需要插入图片)
保存在服务端的键值对
1. 请求来了之后,还是生成随机字符串
2. 以随机字符串为key,在服务端生成一个大字典,真正保存数据是value
3. 把随机字符串以cookie的形式回复给浏览器
4. 下一次请求再来的时候,会携带上一步的随机字符串
5. 从请求中拿到随机字符串,
6. 去后端以 该随机字符串为key找对应的value
7. value里面存的就是真正有用的数据
![]()
3. Django中如何使用Session
1. 无论设置Session还是获取Session都是针对request对象来操作
2. 设置Session
request.session["key"] = "value"
request.session.setdefault('k1', 'v1') # 存在则不设置
3. 获取session
request.session.get("key") # 如果没有key则返回None 推荐使用
request.session["key"] # 如果没有key则会报错
4. 删除session
1. 将所有Session失效日期小于当前日期的数据删除
request.session.clear_expired()
2. 删除当前的会话数据并删除会话的Cookie
request.session.flush()
3. 删除session
del request.session['k1']
4. 删除当前会话的所有session
request.session.delete()
5. 其他常用命令
1. 设置超时时间
request.session.set_expiry(7)
* 如果value是个整数,session会在些秒数后失效。
* 如果value是个datatime或timedelta,session就会在这个时间后失效。
* 如果value是0,用户关闭浏览器session就会失效。
* 如果value是None,session会依赖全局session失效策略。
2. 获取会话session的key
request.session.session_key
3. 检查会话session的key在数据库中是否存在
request.session.exists("session_key")
6. Django中的Session配置(settings)
1. 数据库Session
SESSION_ENGINE = 'django.contrib.sessions.backends.db' # 引擎(默认)
2. 缓存Session
SESSION_ENGINE = 'django.contrib.sessions.backends.cache' # 引擎
SESSION_CACHE_ALIAS = 'default' # 使用的缓存别名(默认内存缓存,也可以是memcache),此处别名依赖缓存的设置
3. 文件Session
SESSION_ENGINE = 'django.contrib.sessions.backends.file' # 引擎
SESSION_FILE_PATH = None # 缓存文件路径,如果为None,则使用tempfile模块获取一个临时地址tempfile.gettempdir()
4. 缓存+数据库
SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db' # 引擎
5. 加密Cookie Session
SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies' # 引擎
其他公用设置项:
SESSION_COOKIE_NAME = "sessionid" # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串(默认)
SESSION_COOKIE_PATH = "/" # Session的cookie保存的路径(默认)
SESSION_COOKIE_DOMAIN = None # Session的cookie保存的域名(默认)
SESSION_COOKIE_SECURE = False # 是否Https传输cookie(默认)
SESSION_COOKIE_HTTPONLY = True # 是否Session的cookie只支持http传输(默认)
SESSION_COOKIE_AGE = 60 * 60 * 24 * 2 # Session的cookie失效日期(2周)(默认)
SESSION_EXPIRE_AT_BROWSER_CLOSE = False # 是否关闭浏览器使得Session过期(默认)
SESSION_SAVE_EVERY_REQUEST = False # 是否每次请求都保存Session,默认修改之后才保存(默认)
二. 分页:https://www.cnblogs.com/liwenzhou/p/8343243.html最下面
1. 如何在单独的一个脚本文件中使用Django的一些变量或方法
#!/usr/bin/env python3
import os
if __name__ == '__main__':
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "about_session.settings")
import django
django.setup()
from app01 import models
# 批量导入500条数据
data = [models.User(username="user{}".format(i), password="123") for i in
range(1, 501)]
models.User.objects.bulk_create(data)
注释:bulk_create() Django ORM批量创建的一个方法
2. 分页:
每页显示10条
1 0->10
2 10->20
3 20->30
n (n-1)*10->n*10
![]()
#!/usr/bin/env python3
"""
分页功能
"""
class Paging(object):
def __init__(self, current_page, total_count, url_prefix, per_page=10, max_show=11):
"""
初始化一个自定义的分页实例
:param current_page: 当前页码
:param total_count: 总的数据量
:param url_prefix: 分页中a标签的url前缀
:param per_page: 每一个显示多少条数据
:param max_show: 页面上最多显示多少个页码
"""
self.total_count = total_count
self.per_page = per_page
self.max_show = max_show
self.url_prefix = url_prefix
# 最多显示页码数的一半
half_show = max_show // 2
# 因为URL取到的参数是字符串格式,需要转换成int类型
try:
current_page = int(current_page)
except Exception as e:
# 如果输入的页码不是正经页码,默认展示第一页
current_page = 1
# 求总共需要多少页显示
total_page, more = divmod(total_count, per_page)
if more:
total_page += 1
# 如果输入的当前页码数大于总数据的页码数,默认显示最后一页
if current_page > total_page:
current_page = total_page
self.current_page = current_page
# 计算一下显示页码的起点和终点
show_page_start = current_page - half_show
show_page_end = current_page + half_show
# 特殊情况特殊处理
# 1. 当前页码 - half_show <= 0
if current_page - half_show <= 0:
show_page_start = 1
show_page_end = max_show
# 2. 当前页码数 + hale_show >= total_page
if current_page + half_show >= total_page:
show_page_end = total_page
show_page_start = total_page - max_show + 1
# 3. 总共需要的页码数 < max_show
if total_page < max_show:
show_page_start = 1
show_page_end = total_page
self.show_page_start = show_page_start
self.show_page_end = show_page_end
self.total_page = total_page
@property
def start(self):
"""
数据切片的起点
:return:
"""
return (self.current_page - 1) * self.per_page
@property
def end(self):
"""
数据切片的终点
:return:
"""
return self.current_page * self.per_page
@property
def num(self):
"""
分页起始序号
:return:
"""
return (self.current_page - 1) * self.max_show
def page_html(self):
"""
分页的html代码
:return:
"""
tmp = []
page_html_start = '<nav aria-label="Page navigation" class="text-center"><ul class="pagination">'
page_html_end = '</ul></nav>'
tmp.append(page_html_start)
# 添加一个首页
tmp.append('<li><a href="/{}?page=1">首页</a></li>'.format(self.url_prefix))
# 添加一个上一页
# 当当前页是第一页的时候不能再点击上一页
if self.current_page - 1 <= 0:
tmp.append(
'<li class="disabled"><a href="#" aria-label="Previous"><span aria-hidden="true">«</span></a></li>')
else:
tmp.append(
'<li><a href="/{}?page={}" aria-label="Previous"><span aria-hidden="true">«</span></a></li>'.format(
self.url_prefix, self.current_page - 1))
# for循环添加要展示的页码
for i in range(self.show_page_start, self.show_page_end + 1):
# 如果for循环的页码等于当前页码,给li标签加一个active的样式
if self.current_page == i:
tmp.append('<li class="active"><a href="/{1}?page={0}">{0}</a></li>'.format(i, self.url_prefix))
else:
tmp.append('<li><a href="/{1}?page={0}">{0}</a></li>'.format(i, self.url_prefix))
# 添加一个下一页
# 当前 当前页已经是最后一页,应该不让下一页按钮能点击
if self.current_page + 1 > self.total_page:
tmp.append(
'<li class="disabled"><a href="#" aria-label="Previous"><span aria-hidden="true">»</span></a></li>')
else:
tmp.append(
'<li><a href="/{}?page={}" aria-label="Previous"><span aria-hidden="true">»</span></a></li>'.format(
self.url_prefix, self.current_page + 1))
# 添加一个尾页
tmp.append('<li><a href="/{}?page={}">尾页</a></li>'.format(self.url_prefix, self.total_page))
tmp.append(page_html_end)
page_html = "".join(tmp)
return page_html
后端代码-封装模块
![]()
from django.shortcuts import render
from app01 import models
from public.paging import Paging
# Create your views here.
def user_list(request):
"""
显示用户列表
:param request:
:return:
"""
if request.method == "GET":
# 查找到所有的用户
books = models.User.objects.all()
# 拿到总数据量
total_count = books.count()
# 从url拿到page参数
current_page = request.GET.get("page", None)
page_obj = Paging(current_page, total_count, url_prefix="user_list", max_show=7)
# 对总数据进行切片,拿到页面显示需要的数据
data = books[page_obj.start:page_obj.end]
page_html = page_obj.page_html()
return render(request, "user_list.html", {"data": data, "num": page_obj.num, "page_html": page_html})
后端代码-使用模块
![]()
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>用户列表</title>
<link rel="stylesheet" href="/static/bootstrap/css/bootstrap.min.css">
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<table class="table table-bordered">
<thead>
<tr>
<th>#</th>
<th>用户名</th>
</tr>
</thead>
<tbody>
{% for user in data %}
<tr>
<td>{{ forloop.counter|add:num }}</td>
<td>{{ user.name }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{{ page_html|safe }}
</div>
</div>
</div>
</body>
</html>
前端代码-显示分页
三. 中间件:https://www.cnblogs.com/liwenzhou/p/8761803.html
1. 什么时候使用中间件?
当需要在全局改变Django框架的输入输出时
2. 中间件不宜添加过多,功能过于复杂
否则会增加请求的响应时间
3. Django如何使用
1. 五个方法(三个常用)
主要记忆:执行时间、执行顺序、参数和返回值
1. process_request(self,request)
1. 执行时间
在执行视图函数之前执行
2. 执行顺序
按照注册的顺序执行
3. 参数和返回值
1. request参数和视图函数中是同一个对象
2. 返回值:
1. 返回None:请求继续往后执行
2. 返回响应对象:请求就结束了,要返回响应了
2. process_response(self, request, response)
1. 执行时间
视图函数执行之后(拿到响应对象之后)
2. 执行顺序
按照注册的倒序执行
3. 参数和返回值
1. 参数:request请求对象
response响应对象
2. 返回值:
只能返回响应对象
1. 返回默认的
2. 自己生成一个响应对象返回
3. process_view(self, request, view_func, view_args, view_kwargs)
1. 执行时间
视图函数之前,在urls.py找到将要执行的视图函数之后
2. 执行顺序
注册的顺序执行
3. 参数和返回值
1. 参数:
1. request: 请求对象
2. view_func:将要执行的视图函数
2. 返回值:
1. 返回None:继续往后执行
2. 返回响应对象,直接跳出,按照process_response方法的顺序执行
有条件触发:
4. process_template_response(self,request,response)
1. 执行时间:
视图函数之后,并且返回的响应对象是要有render方法
2. 执行顺序:
按照注册的倒序执行
3. 返回值:
对传递过来的响应对象,调用其render方法,把返回值向后继续传递
5. process_exception(self, request, exception)
1. 执行时间:
当视图函数中抛出异常的时候才执行
2. 执行顺序:
注册的倒序
3. 参数和返回值
exception:视图函数中抛出的异常
返回响应对象,就跳出按照process_response方法的顺序执行
![]()
代码示例:
------------------------------------------------------------------------------
在项目目录下创建py文件
from django.utils.deprecation import MiddlewareMixin
class MD1(MiddlewareMixin):
def process_request(self, request):
print("MD1里面的 process_request")
class MD2(MiddlewareMixin):
def process_request(self, request):
print("MD2里面的 process_request")
pass
-------------------------------------------------------------------------------
在settings.py的MIDDLEWARE配置项中注册上述两个自定义中间件
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'middlewares.MD1', # 自定义中间件MD1
'middlewares.MD2' # 自定义中间件MD2
]
代码示例
![]()
四. ORM(多对多) https://www.cnblogs.com/liwenzhou/p/8660826.html
1. ORM多对多字段
class Book(models.Model):
"""
图书表
"""
name = models.CharField(max_length=24)
publisher = models.ForeignKey(to="Publisher")
class Author(models.Model):
"""
作者表
多对多,自动帮我们在数据库建立第三张关系表
"""
name = models.CharField(max_length=24)
books = models.ManyToManyField(to="Book", related_name="authors")
参数:
- to:表示和哪张表建立多对多的关系
- related_name:表示返乡查询时使用的那个字段名,默认反向查询时使用表名_set的方式
2. 多对多字段的方法
1. 查询
# 多对多 基于对象的查询
# 正向查询
print(models.Author.objects.first().books.all())
# 反向查询
print(models.Book.objects.first().authors.all())
# 多对多 基于QuerySet 的查询
# 正向查询
print(models.Author.objects.all().values("books__name"))
# 反向查询
print(models.Book.objects.all().values("authors__name"))
2. 删除
1. 从关联对象集中移除执行的model对象
models.Book.objects.first().authors.remove(3)
2. 从关联对象集中移除一切对象。
models.Book.objects.first().authors.clear()
3. 添加
1. 当form表单提交的数据是列表(多选的select\多选的checkbox)取值?
request.POST.getlist("hobby")
2. .set([id1,id2,...]) 参数是一个列表 --> 删除原来的设置新的
models.Author.objects.first().books.set([9])
print(models.Author.objects.first().books.all())
3. .add(id值) --> 在原来的基础上增加新的纪录
models.Author.objects.first().books.add(9)
print(models.Author.objects.first().books.all())
五. ajax:https://www.cnblogs.com/liwenzhou/p/8718861.html
1. stringify与parse方法
JavaScript中关于JSON对象和字符串转换的两个方法:
1. JSON.parse(): 用于将一个 JSON 字符串转换为 JavaScript 对象
JSON.parse('{"name":"Q1mi"}');
JSON.parse('{name:"Q1mi"}') ; // 错误
JSON.parse('[18,undefined]') ; // 错误
2. JSON.stringify(): 用于将 JavaScript 值转换为 JSON 字符串。
JSON.stringify({"name":"Q1mi"})
2. 目前已知浏览器和服务端发请求的方式
1. 浏览器地址栏 输入url直接回车 GET
2. a标签 GET
3. form表单 GET/POST
4. ajax GET/POST
3. ajax的特点:
优点:
1. 偷偷发请求,用户无感知
2. 局部刷新 相对于其他请求方式而言,返回的数据量小
3. 同一个页面可以发送多次请求 异步
缺点:
1. 如果滥用,对服务端的压力比较大
4. ajax的使用:
jQuery版:
导入jQuery
$.ajax({
url: "往哪里发请求",
type: "发送请求的类型",
data: {
"k1": "v1",
"k2": "v2",
},
success:function(res){
}
})
![]()
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>注册页面</title>
<link rel="stylesheet" href="/static/plugins/bs/css/bootstrap.min.css">
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-4 col-md-offset-2">
<form action="" method="post" class="form-signin">
{% csrf_token %}
<h2 class="form-signin-heading">请注册</h2>
<div class="username">
<label for="username" class="sr-only">用户名</label>
<input type="text" id="username" name="username" class="form-control" placeholder="Username"
required
autofocus>
</div>
<label for="password" class="sr-only">密码</label>
<input type="password" id="password" name="password" class="form-control" placeholder="Password"
required>
<button class="btn btn-lg btn-primary btn-block" type="submit">注册</button>
</form>
</div>
</div>
</div> <!-- /container -->
<script src="/static/plugins/jquery-3.3.1.min.js"></script>
<script>
$(function () {
$("#username").blur(function () {
$.ajax({
url: "/check/",
type: "post",
data: {
"username": $("#username").val(),
"csrfmiddlewaretoken": $("[name = 'csrfmiddlewaretoken']").val()
},
success: function (res) {
if (res == 0) {
$(".username").addClass("has-error")
}
else{
$(".username").addClass("has-success").removeClass("has-error")
}
}
})
})
})
</script>
</body>
</html>
ajax-前端代码
![]()
from django.shortcuts import render, HttpResponse
from app01 import models
# Create your views here.
def reg(request):
if request.method == "GET":
return render(request, "reg.html")
def check(request):
username = request.POST.get("username")
obj = models.User.objects.filter(username=username)
if not obj.exists():
return HttpResponse("1")
else:
return HttpResponse("0")
ajax-后端代码
5. AJAX请求如何设置csrf_token
$.ajax({
url: "/cookie_ajax/",
type: "POST",
data: {
"username": "Q1mi",
"password": 123456,
"csrfmiddlewaretoken": $("[name = 'csrfmiddlewaretoken']").val() // 使用jQuery取出csrfmiddlewaretoken的值,拼接到data中
},
success: function (data) {
console.log(data);
}
})