分页的原理、分页类的使用、cookie和session的介绍、Django操作cookie、property装饰器、safe过滤器、哪些SQL语句不会走索引、慢SQL查询的优化方法

一、推导分页的原理

分页:当我们要展示的数据特别多的时候,一页展示不完,这个时候我们需要把要展示的数据分成多页展示

分页中需要的几个参数:
1. 总数据有多少条
2. 每页展示多少条数据(如,自己规定的10)
3. 一共展示多少页
4. 总页数 = 总数据量 / 每页展示多少条数据
5. 当前第几页(前端传过去的)

总页数怎么算?
"""
	总条数       每页展示的数据     页数
	100				10			10
	101				10			11
	99				10			10
	...
	divmod(100, 10)
"""

---------------------------------------------------------------------------------
自己推导代码
后端代码:
def index(request):
    # 当前是第几页  current_page是字符串
    current_page = request.GET.get('page')
    try:
        current_page = int(current_page)
    except:
        current_page = 1

    # 每页展示的数据
    per_page_num = 10
    # 起始页
    start_page = (current_page - 1) * per_page_num
    # 终止页
    end_page = current_page * per_page_num

    # 总数量
    # 先从数据库中查出有多少数据
    user_list = models.UserInfo.objects.all()
    # 再计算总的数量
    all_count = user_list.count()

    # 计算中总页码数
    page_num, more = divmod(all_count, per_page_num)  # 返回值是一个是一个元组,一个是夜数,一个是余数
    if more:
        page_num += 1

    # 由于前端页面不能进行range运算,所以把前端代码拿到后端来处理
    html = ''

    # 防止页数小于1
    xxx = current_page
    if current_page < 6:
        current_page = 6
    # # 防止页数大于总页数
    # if current_page > page_num:
    #     ...
    
    # for i in range(page_num):
    # 展示10页
    for i in range(current_page - 5, current_page + 6):
        # html += '
  • 1
  • '
    # 让展示页高亮 if xxx == i: html += '
  • %s
  • '
    % (i, i) else: html += '
  • %s
  • '
    % (i, i) ''' 当前页 起始页 终止页 1 0 5 2 5 10 3 10 15 4 15 20 ''' # 切片展示10条 # user_list = models.UserInfo.objects.all()[0:10] user_list = models.UserInfo.objects.all()[start_page:end_page] return render(request, 'index.html', locals()) 前端代码: <nav aria-label="Page navigation"> <ul class="pagination"> <li> <a href="#" aria-label="Previous"> <span aria-hidden="true">&laquo;</span> </a> </li> {#
  • 1
  • #}
    {#
  • 1
  • #}
    {#
  • 1
  • #}
    {#
  • 1
  • #}
    {#
  • 1
  • #}
    {# 需要使用safe进行页面过滤,否则展示的只是标签 #} {{ html|safe }} <li> <a href="#" aria-label="Next"> <span aria-hidden="true">&raquo;</span> </a> </li> </ul> </nav>

    二、分页类的使用

    注意:
    	以后我们针对像分页类这种第三方工具,我们一般在Django中创建一个utils文件夹保存
    
    
    from utils.mypage import Pagination
    current_page =  request.GET.get('page')
    try:
        current_page = int(current_page)
    except Exception:
            current_page = 1
    
    user_list  = models.UserInfo.objects.all()
    all_count = user_list.count()
    page_pbj = Pagination(current_page, all_count, per_page_num=10)
    
    user_list = user_list[page_pbj.start:page_pbj.end]
    
    page_html = page_pbj.page_html()
    return render(request, 'index.html', locals())
    
    

    三、cookie和session的介绍(重要)

    HTTP协议的特性之一:无状态
    
    背景信息:
    	1. 早期的时候一些网站都是静态网站,不需要登录,比如:新闻类、博客等
        2. 随着技术的发展以及用户的要求,诞生了诸如支付宝、淘宝、京东等电商网站,这些网站就必须要求用户登录,如果不登录,商家怎么知道是谁买的东西? 登录的目的其实就是商家可以识别这个用户是谁。
       	3. 诞生了保存用户状态的技术:cookie和session
        
    """
    以登录功能为例:
    	1.分析cookie 的原理
    		你进入到一个淘宝网站,第一次肯定需要登录的,如果登录成功,
    	淘宝网站不保存你的用户信息,意味着你下次再访问淘宝的时候,就需要从新登录,
    	每一次访问淘宝的页面都需要登录,如果真的是这样,你想用吗?
    		
    	2.如何解决上述问题?
    		这个时候就利用到了cookie,比如你第一次登录成功之后,django后端让浏览器把你的用户名
    和密码保存在浏览器中,你下次再访问淘宝页面的时候,浏览器会自动把它之前保存的用户名和密码
    一块提交到Django后端,Django后端每次拿到浏览器发过来的用户名和密码再次做验证.
    
    	3.上述的做法有没有什么问题? 有
    	数据保存在浏览器上面,很明显的问题是:数据不够安全
    	
    	4.如何解决上述数据不安全的问题
    		其实是做了优化:把原本存在浏览器上的数据存到后端,就称之为是session,
    	session就解决了cookie数据不安全的问题
    	
    	5.session的原理:
    		以登录功能为例:
    			第一次登录成功之后,把用户信息保存在后端,其中,django默认是把用户信息
    		保存在数据表中了django_session表中了
    			
            1. 先生成一个随机字符串
            2. 把用户的信息保存在django_session表中
                session_key			session_data        expire_date
                随机字符串1				用户信息1
                随机字符串2				用户信息2
                随机字符串3				用户信息3
                随机字符串4				用户信息4
                随机字符串5				用户信息5
            3. Django后端会把随机字符串告诉浏览器保存起来
            4. 以后用户每次访问页面的时候,浏览器每次都要把随机字符串提交过来,
            5. Django后端拿到随机字符串,去django_session表中查询数据,如果查到了,
            6. 就说明以前登录成功了,如果查不到,就说明还没有登录
            
    select * from django_session where session_key = ''
            
    """
     
    问题1:如果都把用户信息保存在django_session表中,有没有其他问题?
    	最大的问题就是数据量一旦很大,查询就是致命的
    
    问题2:怎么解决这个问题?
    	需要用到token
    	token就是一个随机字符串------->保存着用户信息---------->字符串返回给前端
    		------>每次都把token提交过来------>后端做验证.
    
    加密和解密都是后端做的,前端只需要每次把这个串来回传递就行了
    
    
    # jwt------------>三段式--------->
    
    跟面试相关的:
    	1. 保存在浏览器上的数据都称之为是cookie
        2. session是保存在服务端的
        3. session的数据相对更加安全,cookie不够安全
        4. session是基于cookie工作的? 对还是不对? 对
        5. django让浏览器保存cookie,用户有权可以设置浏览器不保存
        6. session离开cookie一定就不能工作了,对还是不对?
    
    

    案例使用

    login.html代码
    <form action="" method="post">
        username: <input type="text" name="username">
        password: <input type="password" name="password">
        <input type="submit">
    </form>
    
    
    后端代码:
    # 基于cookie的登录功能
    def login(request):
        if request.method == 'POST':
            username = request.POST.get('username')
            password = request.POST.get('password')
    
            if username == 'jerry'  and password == '123':
    
                print('登录成功')
                # 保存用户的信息,使用cookie保存
                obj = redirect('/home')
                # 设置5秒后自动删除
                obj.set_cookie('username', 'jerry', max_age=5)
                return obj
    
        return render(request, 'login.html', locals())
    
    
    def login_auth(func):
        # def inner(*args, **kwargs):
        #     request = args[0]
        def inner(request, *args, **kwargs):
            if request.COOKIES.get('username'):
                return func(request, *args, **kwargs)
            else:
                return redirect('/login/')
        return inner
    
    
    @login_auth  # home = login_auth(home)
    def home(request):
        '''访问这个页面必须登录才能访问'''
        # # 判断是否有cookie
        # print(request.COOKIES.get('username'))
        # if request.COOKIES.get('username'):
        #     return HttpResponse('登录成功才能访问我')
        # else:
        #     return redirect('/login/')
    
        return HttpResponse('登录成功才能访问我')
    
    

    http协议的特性

    HTTP(Hypertext Transfer Protocol)是一种用于在网络中传输超文本(Hypertext)数据的协议。它是客户端-服务器模型中的一部分,用于从Web服务器获取网页和其他资源。以下是HTTP协议的一些主要特性:
    
    1. **无连接性(Connectionless)**:每次客户端与服务器之间进行通信时,都会创建一个新的连接,完成后即关闭连接。这种特性可以减轻服务器的负担,但在多个请求之间需要重新建立连接,可能导致一些额外的延迟。
    
    2. **无状态性(Stateless)**:HTTP协议本身是无状态的,即服务器不会保留关于前后请求之间状态的信息。每个请求都是相互独立的,服务器不会记住之前的请求。这导致在处理需要跨请求的状态时,需要使用一些其他机制,如Cookies或Session。
    
    3. **请求-响应模型**:HTTP基于请求-响应模型,客户端发送一个请求给服务器,服务器处理请求并返回相应的响应。请求和响应都包含了头部信息和可选的消息体。
    
    4. **可扩展性**:HTTP的头部(Header)允许添加自定义的字段,这使得协议具有很强的可扩展性,可以满足不同的需求。
    
    5. **URI(Uniform Resource Identifier)**:HTTP使用统一资源标识符来标识网络上的资源,通常用URL(Uniform Resource Locator)来表示资源的地址。
    
    6. **方法(Methods)**:HTTP定义了一系列方法,如GET、POST、PUT、DELETE等,用于指示服务器执行特定的操作。常用的有GET用于获取资源,POST用于提交数据等。
    
    7. **状态码(Status Codes)**:HTTP响应包含一个状态码,用于表示服务器对请求的处理结果。常见的状态码包括200(成功)、404(未找到)和500(服务器内部错误)等。
    
    8. **缓存**:HTTP支持客户端缓存和服务器端缓存。通过缓存,可以减少网络请求和提高性能。
    
    9. **安全性**:HTTP支持加密协议,如HTTPS(HTTP Secure),用于通过SSL或TLS加密数据传输,提供数据的安全性。
    
    10. **管道化(Pipelining)**:HTTP允许客户端发送多个请求到服务器,而无需等待每个请求的响应。这可以提高请求的处理效率。
    
    HTTP协议在Web开发中起到了非常重要的作用,它是构建互联网应用的基础之一。随着Web技术的发展,HTTP协议也在不断演进,如HTTP/1.1、HTTP/2和HTTP/3等版本的出现。
    
    

    四、Django操作cookie

    # 在Django这种如何使用cookie、
    
    三板斧:
    return HttpResponse
    
    return render
    
    return redirect
    
    
    obj = HttpResponse
    return obj
    
    obj = render
    return obj
    
    obj = redirect
    return obj
    
    # 操作cookie的时候,就用到了这个obj对象
    # 案例:基于cookie的登录功能
    
    

    五、 session是基于cookie工作的吗

    	是的,`session` 是基于 `cookie` 工作的,尤其是在 Web 开发中。
    	`cookie` 是一种在客户端(浏览器)存储数据的机制,
    		而 `session` 是一种在服务器端存储数据的机制。
    	`cookie` 通常被用于存储会话标识符,以便服务器可以根据会话标识符识别用户,
    		并在服务器端管理会话数据。
    
    以下是 `session` 如何基于 `cookie` 工作的一般流程:
    1. **客户端发送请求**:
       当用户首次访问网站时,服务器会为其分配一个唯一的会话标识符,
       并将该标识符作为 `cookie` 发送给客户端。
    2. **客户端存储 cookie**:
       客户端的浏览器会将接收到的 `cookie` 存储在本地。
       该 `cookie` 包含会话标识符,以及其他可能的信息。
    3. **客户端发送 cookie**:
       每次客户端向服务器发送请求时,浏览器会自动将与该域关联的 `cookie` 一并发送给服务器。
       这样,服务器就可以根据会话标识符识别用户。
    4. **服务器识别会话**:
       服务器收到请求后,会解析其中的 `cookie`,提取会话标识符。
       然后,服务器会使用该标识符来查找或创建用户的会话,并将会话数据存储在服务器端。
    5. **会话数据操作**:
       服务器可以根据会话标识符在会话中存储和检索数据,以保持用户状态和信息。
       在每次请求中,服务器都可以访问会话数据并对其进行修改。
    6. **会话结束**:
       会话可以在用户退出登录、超时或其他条件满足时结束。
       服务器会根据会话标识符清除或关闭相应的会话数据。
    总之,`session` 使用 `cookie` 来在客户端和服务器之间传递会话标识符,以便服务器可以管理用户的会话数据。尽管 `session` 是基于 `cookie` 工作的,但会话数据实际上存储在服务器端,这有助于保护数据的安全性和隐私。
    

    六、 都把信息保存在session中会有什么问题

    	将大量信息保存在会话(session)中可能会导致一些问题,特别是在 Web 应用程序中。虽然会话是一种方便的方式来在不同页面和请求之间保持用户状态和数据,但过度使用会话会带来以下问题:
    1. **内存占用增加**:
       每个用户的会话数据都需要在服务器内存中保存,如果会话数据过大或用户数过多,
       会导致服务器内存占用增加,影响系统的性能和扩展性。
    2. **性能下降**:
       会话数据的读写操作会消耗服务器资源,如果会话数据量大,
       读写操作会变得更加耗时,从而降低系统的性能。
    3. **服务器负担增加**:
       大量的会话数据需要服务器频繁地读写数据,增加服务器的负担,可能导致服务器响应变慢,甚至崩溃。
    4. **扩展困难**:
       如果应用程序需要扩展到多台服务器上,会话数据的同步和共享可能变得复杂,增加了系统的维护难度。
    5. **安全问题**:
       将敏感信息存储在会话中可能会增加安全风险,尤其是如果会话管理不当或会话被劫持。
    6. **用户体验下降**:
       大量的会话数据会影响用户的页面加载速度,降低用户体验。
       
    	为了避免上述问题,应当合理使用会话,只保存必要的信息,如用户登录状态、权限等。对于大量的临时数据,可以使用其他方法,如数据库存储、缓存等,以减轻会话的负担。在设计会话时,需要权衡各方面的考虑,保持合理的会话数据量,以保证应用程序的性能和稳定性。
    
    

    七、session离开cookie就不能够工作了吗

    	在 Web 开发中,`session` 并不完全离开 `cookie` 就无法工作,
    	但是 `cookie` 是最常见和默认的用于在客户端和服务器之间传递会话标识符的机制。
    	虽然可以使用其他方式来传递会话标识符,但这些方法可能需要额外的配置和处理。
    
    除了使用 `cookie`,还可以使用其他传递会话标识符的方式,例如:
    1. **URL 参数**:
       可以将会话标识符作为 URL 参数传递给服务器。但这会将会话标识符暴露在 URL 中,
       可能会引发安全隐患,因为 URL 可能会被保存在浏览器历史记录、日志文件等地方。
    2. **隐藏表单字段**:
       在表单中添加一个隐藏字段,将会话标识符作为值传递给服务器。
       这也会将会话标识符暴露在页面源代码中,有一定的安全风险。
    3. **HTTP 请求头**:
       将会话标识符作为 HTTP 请求头的一部分发送给服务器。
       这种方式需要客户端和服务器都进行额外的配置。
    
    	尽管可以使用上述方式来传递会话标识符,但它们通常不如 `cookie` 方式方便和常用。`cookie` 具有很多优点,比如自动发送、存储在客户端等。因此,尽管 `session` 并不完全依赖于 `cookie`,但 `cookie` 是实现会话管理的主要机制之一。
    
    

    八、property装饰器

    	`property` 是 Python 中的一个内置装饰器,用于将一个方法转换为属性,
    使其在访问时可以像访问属性一样,而不需要调用方法。
    
    	使用 `property` 装饰器可以隐藏方法的调用细节,从而提供更加直观和方便的访问方式。
    它常用于创建类的属性,这些属性可能需要进行计算或逻辑处理。
    
    以下是一个简单的示例,演示了如何使用 `property` 装饰器:
    
    class Circle:
        def __init__(self, radius):
            self.radius = radius
    
        @property
        def area(self):
            return 3.14 * self.radius ** 2
    
        @property
        def circumference(self):
            return 2 * 3.14 * self.radius
    
    # 创建 Circle 实例
    circle = Circle(5)
    
    # 访问属性(实际上调用了方法)
    print(circle.area)  # 计算并打印面积
    print(circle.circumference)  # 计算并打印周长
    
    
    在上面的示例中,`area` 和 `circumference` 方法被装饰为属性,因此可以像访问普通属性一样访问它们。当你访问 `circle.area` 时,实际上会调用 `area` 方法并返回计算的结果。
    
    需要注意的是,`property` 装饰器只能用于方法,它不允许直接对属性赋值,因为它只定义了属性的获取行为,而没有定义属性的设置行为。如果需要实现设置行为,可以使用 `@property` 装饰器结合其他方法(如 `@<属性名>.setter`)来实现。
    
    

    九、safe过滤器

    在 Django 模板语言中,`safe` 是一个用于标记字符串在模板渲染时不被转义的过滤器。
    默认情况下,Django 会对在模板中输出的变量进行 HTML 转义,以防止跨站点脚本(XSS)攻击。
    但是,在某些情况下,你可能希望将特定字符串输出到模板时保持原样,不进行转义,
    这时可以使用 `safe` 过滤器。
    
    `safe` 过滤器的作用是告诉 Django 不要对这个变量进行转义。这在你确定变量内容是安全的、
    不含有恶意代码,或者你希望保持 HTML 标签等内容的原样时非常有用。
    
    示例:
    <!-- 模板中的变量 -->
    {% with html_content="Hello, world!" %}
      <!-- 使用 safe 过滤器输出变量内容 -->
      {{ html_content|safe }}
    {% endwith %}
    
    
    在上述示例中,`html_content` 变量包含了一个带有 `<strong>` 标签的字符串。
    使用 `safe` 过滤器,字符串中的 HTML 标签不会被转义,而是原样输出到模板中。
    
    **注意**:使用 `safe` 过滤器要谨慎,确保输出的内容是安全的。如果你输出了不受信任的内容,
    可能会引发跨站点脚本(XSS)漏洞。
    
    如果你确定输出的内容是安全的,且你需要保持原样输出,可以使用 `safe` 过滤器。
    但是,在大多数情况下,建议仍然对输出的内容进行适当的转义,以防止潜在的安全问题。
    
    

    十、哪些SQL语句不会走索引

    1. **使用函数对列进行操作:** 如果在查询中对列应用了函数,
    	比如`WHERE UPPER(column_name) = 'VALUE'`,这可能会导致索引无法使用。
    	函数会对列的值进行处理,使索引失效。
    2. **使用通配符开头的LIKE查询:** 当使用通配符(例如%,_)开头的LIKE查询时,
    	索引通常无法被利用。例如,`WHERE column_name LIKE '%value'`3. **使用OR条件:** 对于OR条件,如果每个OR子句涉及不同的列,索引可能不会被使用。
    4. **范围查询:** 如果在查询中使用范围操作符(例如`BETWEEN``<``>`),
    	则索引可能无法被充分利用。
    5. **列类型转换:** 当在查询中对列进行类型转换时,索引可能会失效。
    	例如,`WHERE CAST(column_name AS CHAR) = 'value'`6. **使用NOT操作:** 使用`NOT`操作会导致索引不被使用,因为数据库需要扫描所有不匹配的行。
    7. **数据量小的表:** 对于非常小的表,使用索引可能不会带来明显的性能提升,
    	因为数据库可能会选择执行全表扫描。
    8. **排序操作:** 当使用`ORDER BY`进行排序时,索引可能会在查询过程中被使用,但在某些情况下可能会选择全表扫描来避免额外的排序操作。
    
    
    

    十一、慢SQL查询的优化方法

    1. **使用合适的索引:** 确保你的查询涉及的列都有适当的索引。使用 `EXPLAIN` 命令来查看查询执行计划,以确定是否使用了索引。
    
    2. **避免全表扫描:** 尽量避免全表扫描,因为它会消耗大量资源。确保你的查询条件充分利用了索引,以避免全表扫描。
    
    3. **避免函数操作:** 避免在查询中对列使用函数操作,因为函数可能会使索引失效。如果可能,将函数操作移到查询外部。
    
    4. **优化 WHERE 子句:** WHERE 子句中的条件应尽量简单且有效。避免复杂的逻辑或多重嵌套条件,这可能会影响查询性能。
    
    5. **避免使用 SELECT *** 明确指定需要的列,而不是使用 `SELECT *`。只选择需要的列可以减少数据传输和内存占用。
    
    6. **分页优化:** 对于分页查询,使用合适的 LIMITOFFSET,避免大 OFFSET 导致的性能问题。另一种方法是使用游标(cursor)来实现分页。
    
    7. **连接操作优化:** 对于连接查询,确保连接条件使用了索引,并选择合适的连接类型(INNER JOINLEFT JOIN 等)。
    
    8. **表设计优化:** 合理设计数据库表结构,避免过度规范化和冗余。冗余数据可以加速一些查询。
    
    9. **定期分析和优化表:** 使用 `ANALYZE TABLE``OPTIMIZE TABLE` 命令定期分析和优化表,以消除碎片和更新统计信息。
    
    10. **使用缓存:** 对于频繁访问的查询,可以使用查询缓存(如果已启用)或应用程序级别的缓存。
    
    11. **异步处理:** 对于可能会耗时较长的查询,考虑将其拆分为异步任务,以避免影响实时性能。
    
    12. **数据库服务器参数调整:** 调整数据库服务器的参数,例如缓冲区大小、并发连接数等,以优化性能。
    
    13. **使用数据库性能工具:** 使用数据库性能分析工具,如 MySQL 的 `EXPLAIN`、Percona Toolkit 等,来分析查询执行计划和性能瓶颈。
    
    14. **定位瓶颈:** 使用性能监控工具来定位数据库性能瓶颈,如 CPU、内存、磁盘 I/O 等。
    
    
    

    mark_safe()的使用

    `mark_safe()` 是 Django 模板语言中的一个函数,用于告诉模板引擎某个字符串是安全的,不需要进行转义,可以直接在模板中输出。
    
    在 Django 模板中,默认情况下,变量的输出会被自动进行 HTML 转义,以防止跨站脚本攻击(XSS)。但有时候,你可能需要在模板中输出一些已经是 HTML 代码的内容,而不希望模板引擎对其进行转义。这时就可以使用 `mark_safe()` 函数。
    
    例如,假设你在视图中传递了一个包含 HTML 标签的字符串给模板,你希望这个字符串在模板中原样输出,而不是被转义。你可以使用 `mark_safe()` 函数来标记这个字符串为安全的:
    
    from django.utils.safestring import mark_safe
    
    def my_view(request):
        html_content = "Hello, Django!"
        return render(request, 'my_template.html', {'html_content': mark_safe(html_content)})
    
    在模板中,你可以这样使用这个被标记为安全的变量:
    
    <div>{{ html_content }}</div>
    
    使用 `mark_safe()` 需要小心,因为它告诉模板引擎不要进行转义,如果你将不受信任的内容标记为安全,可能会导致安全风险。通常,只有在你确定内容是安全的情况下才应该使用该函数。
    
    

    你可能感兴趣的:(django,python01,django,sql)