day18-session、ajax、中间件、分页、orm多对多

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">&laquo;</span></a></li>')
        else:
            tmp.append(
                '<li><a href="/{}?page={}" aria-label="Previous"><span aria-hidden="true">&laquo;</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">&raquo;</span></a></li>')
        else:
            tmp.append(
                '<li><a href="/{}?page={}" aria-label="Previous"><span aria-hidden="true">&raquo;</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(下周再讲)
'''


猜你喜欢

转载自www.cnblogs.com/lijie123/p/10251348.html
今日推荐