day18 2018-08-19 1. 讲课内容: 1. session:https://www.cnblogs.com/liwenzhou/p/8343243.html 1. Cookie是保存在浏览器端的键值对 用来解决HTTP请求是无状态的 2. Django里面使用Cookie 1. 设置Cookie 1. 回复响应时设置的 rep = HttpResponse("OK") rep.set_cookie("key", "value", max_age=超时时间(秒)) rep.set_signed_cookie("key", "value", salt="盐", max_age=超时时间(秒)) 2. 获取Cookie 请求来的时候从请求中找cookie 1. request.COOKIES.get("key") 2. request.get_signed_cookie("key", default="", salt="盐") 3. 为何要有session 1. 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" 3. 获取session request.session.get("key") 4. 其余经常使用命令 1. # 将全部Session失效日期小于当前日期的数据删除 request.session.clear_expired() 2. # 删除当前的会话数据并删除会话的Cookie。 request.session.flush() 3. 设置超时时间 request.session.set_expiry(7) 5. 经常使用配置项(写在Settings.py中) # 全局配置session超时时间 SESSION_COOKIE_AGE = 60 * 60 * 24 * 2 # 是否每次请求都刷新session超时时间 SESSION_SAVE_EVERY_REQUEST = True 2. 分页:https://www.cnblogs.com/liwenzhou/p/8343243.html最下面 1. 如何在单独的一个脚本文件中使用Django的一些变量或方法 2. bulk_create() Django ORM批量建立的一个方法 分页: 每页显示10条 1 0-10 2 10-20 3 20-30 n (n-1)*10-n*10 3. 中间件: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. 执行时间: 1. 视图函数以后,而且返回的响应对象是要有render方法 2. 执行顺序: 1. 按照注册的倒序执行 3. 返回值: 1. 对传递过来的响应对象,调用其render方法,把返回值向后继续传递 5. process_exception(self, request, exception) 1. 执行时间: 1. 当视图函数中抛出异常的时候才执行 2. 执行顺序: 1. 注册的倒序 3. 参数和返回值 exception:视图函数中抛出的异常 返回响应对象,就跳出按照process_response方法的顺序执行 2. 额外补充 1. 反射 --> 由一个字符串找到方法、函数(可调用对象) 2. importlib --> 由字符串动态导入 **本身回去查 3. 示例: 限制用户访问我网站的频率,一分钟最多访问3次 15:52:13 15:52:11 15:52:04 15:52:01 { '11.12.13.14': [15:52:11, 15:52:04, 15:52:01] } 4. ORM(多对多) 1. ORM多对多字段 # 多对多,自动帮咱们在数据库创建第三张关系表 books = models.ManyToManyField(to='Book', related_name="authors") 参数: - to:表示和哪张表创建多对多的关系 - related_name:表示返乡查询时使用的那个字段名,默认反向查询时使用表名_set的方式 2. 多对多字段的方法 1. 查询 .all() --> 多对多查询的方法, 2. 删除 3. 添加新做者 1. 当form表单提交的数据是列表(多选的select\多选的checkbox)取值? request.POST.getlist("hobby") 2. .set([id1,id2,...]) 参数是一个列表 --> 删除原来的设置新的 3. .add(id值) --> 在原来的基础上增长新的纪录 3. 13条 1. 返回QuerySet类型的 1. all() 2. filter() 3. exclude() 4. order_by() 5. reverse() 6. distinct() 7. values() -> QuerySet中是字典类型 8. values_list() -> QuerySet中是元祖类型 2. 返回具体对象的 1. get() 2. first() 3. last() 3. 返回数字 1. count() 4. 返回布尔值 1. exist() 5. ajax:https://www.cnblogs.com/liwenzhou/p/8718861.html 1. 目前已知浏览器和服务端发请求的方式 1. 浏览器地址栏 输入url直接回车 GET 2. a标签 GET 3. form表单 GET/POST 4. ajax GET/POST ajax的特色: 优势: 1. 偷偷发请求,用户无感知 2. 局部刷新 相对于其余请求方式而言,返回的数据量小 3. 同一个页面能够发送屡次请求 异步 缺点: 1. 若是滥用,对服务端的压力比较大 ajax的使用: jQuery版: 导入jQuery $.ajax({ url: "往哪里发请求", type: "发送请求的类型", data: { }, success:function(res){ } }) ajax注意事项: data 6. jQuery:https://www.cnblogs.com/liwenzhou/p/8178806.html 1. 选择器 1. 基本选择器 1. id 2. 类 3. 标签 4. 属性 5. 组合 2. 层级选择器 1. 后代选择器 2. 毗邻选择器 3. 儿子选择器 2. .text() 1. 获取标签的文本内容 $("div").text() --> 默认取全部div的文本内容 2. 有参数表示 设置标签的文本内容 $("div").text(‘哈哈’) --> 设置全部div标签的文本为哈哈 3. .html() 1. 获取标签的html内容 $("div").html() --> 默认取第一个div的html内容 2. 有参数表示 设置标签的html内容 $("div").html(‘哈哈’) --> 设置全部div标签的html内容为哈哈 4. val() 1. 获取input标签的值 $("input").val() --> 默认取第一个input的值 2. 有参数表示 设置input标签的值 $("input").val(666) --> 设置全部input标签的值为666 AJAX上传文件,下周再讲 5. Form & ModelForm(下周再讲) 技术的提高只是量的积累,思想的提高才是质的飞跃。 在公司混:政治正确才是最重要的! 2. 练习题: 1. django请求生命周期 2. csrf原理 3. ORM和原生SQL区别? 4. django中装饰器和中间件的应用场景? 5. 为何要使用母板? 6. ORM查询示例: 表结构: 出版社表: ID 名称 图书表: ID 书名称 价格 出版社ID 做者表: ID 做者姓名 做者和图书关系表: ID 图书ID 做业ID 题目: 1. 查询alex出过的全部书籍的名字(多对多) 2. 查询alex的手机号 3. 查询人民出版社出版过的全部书籍的名字以及做者的姓名 4. 统计每一本书的做者个数 5. 统计不止一个做者的图书 6. 根据一本图书做者数量的多少对查询集 QuerySet进行排序 7. 查询各个做者出的书的总价格 3. 做业:主机管理【03】:业务线管理 1. 基于django建立表: 用户表:ID、用户名、密码 业务线表:ID、名称 主机表:ID、主机名、密码、业务线ID 用户和业务线关系表:ID、业务线ID、管理员ID 2. 业务线管理:增删改查(多对多) 3. 使用模板和动态路由 4. 主机管理使用CBV实现 5. 套用BootStrap样式 采分点: 练习题:20 实现全部功能:70 代码写的清晰、健壮、可扩展:10
# 做业:引入框架模板----重要!!!2-3天---1.下次做业添加 0821 ok
# 新增功能:分页 ok
# 需优化:1.cookie和session ---界面跳转存在问题?
# 2.添加ajax局部刷新??
# 3.中间件???
# 4.删除确认
# 重点关注一下 正向查询、反向查询、、、、
# cookie
# github
# 菜鸟教程---python,,,100例练习
'''
0809回顾
cookie
'''
'''
1.session
为何要有session?
cookie的保存内容有限,只有4096;数据都保存在浏览器
原理
django中如何使用?
内容保存在数据库的django_session中,k,v,超时时间
session把设置的kv数据保存在server端,cookie是存放在浏览器端
删除过时的session
book_list注销
session版登陆,本身书写--ok
全局配置session
2.分页
在脚本中操做orm,批量建立数据,提交
insert_book:设置环境,引入,建立数据
页面实现
问题解决:输入字母显示第一页;输入很大的数字,取最后一页
前端中有向上取整?ceil?
页面按钮问题:1.按钮能动态切换显示
2.页面最多显示11个:选中的高亮显示active,页码显示正常不出现0、55等,数据少时
3.显示首页和尾页
4.添加上一页、下一页:第一页不能点击上一页;最后一页同理
---------看分装以前代码views
5.封装成类@property 将方法变为属性,调用时就不用加()啦
出版社分页,使用分装的类;;须要添加a标签对象链接地址
""" 那是一个上午, 写了一个分页的功能,特地封装成了一个类工具,blablabla... """ # 封装分页类 class MyPage(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 (self.current_page - 1) * self.per_page # 数据切片的终点 @property def end(self): return self.current_page * self.per_page # 分页的html代码 def page_html(self): 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 utils import mypage # Create your views here. def book_list(request): # 查找到全部的书籍 books = models.Book.objects.all() # 拿到总数据量 total_count = books.count() # 从url拿到page参数 current_page = request.GET.get("page", None) page_obj = mypage.MyPage(current_page, total_count, url_prefix="book_list", max_show=7) # 对总数据进行切片,拿到页面显示须要的数据 data = books[page_obj.start:page_obj.end] page_html = page_obj.page_html() return render(request, "book_list.html", {"books": data, "page_html": page_html}) def publisher_list(request): publishers = models.Publisher.objects.all() total_count = publishers.count() current_page = request.GET.get("page") # 三行完成分页功能 page_obj = mypage.MyPage(current_page, total_count, url_prefix='publisher_list') data = publishers[page_obj.start:page_obj.end] page_html = page_obj.page_html() return render(request, "publisher_list.html", {"publishers": data, "page_html": page_html})
'''
# 注销 def logout(request): # 清除session数据,让cookie失效 request.session.flush() return redirect("/login/")
'''
3.中间件
importlib本身学习--本身练习代码
5个使用中间件的方法:
process_request(self,request)
process_response(self,request,response)
哈哈----是嘿嘿的相应哈哈
1-3必需要会;4-5了解便可
例子--利用中间件,作频率限制;动态配置频率限制
4.orm多对多
建立库以后,有sqlite3数据库,才能在session中存取数据
用户输入的值,不要用get,用filter
列表--删除--增长-修改
form表单提交的数据是列表(多选的select、checkbox)时,取值request.POST.getlist()
.set([]) 参数是一个列表,重置
.add([]) 增长
最难的地方,判断书默认选中。
第三张表自动封装了保存更新方法。
跨表查询--要掌握
1. 基于对象的查询
1. 正向查
2. 反向查
2. 基于QuerySet的查询
1. 正向查
2. 反向查
'''
'''
5.ajax
JSON.parse 反序列化 字符串----对象
1.json内容回顾: 老师博客中有图
2.ajax:偷偷发请求,用户无感知;局部刷新,返回的数据量小;同一个页面能够发送屡次请求缺点:若是滥用,对服务端压力较大ajax使用:jquery版导入;坑: 多余一层的数据要使用json.stringify 保存setupajax ensure_csrf_cookie数据求和例子;用户名校验例子6.补充:jquery内容''''''下节:删除确认-----------------------------AJAX上传文件,下周再讲--------------------- 5. Form & ModelForm(下周再讲)'''