session的认证机制图解、 drf(过滤、分页、drf的异常处理方式)、补充(DateField和DateTimeField、auto_now_add和auto_now)

认证权限频率

### DateField、DateTimeField
    -auto_now_add=True    # 创建数据时自动添加当前时间
    -auto_now=True           # 每次操作数据时更新为当前时间
    
    
    
# 1 认证---》登录
	-写一个登录接口---》保存用户登录状态
    	-session:request.SESSION['name']='lqz'
        -签发阶段:做三件事:
	        1 生成一个随机字符串  
	        2 django-session表中插入记录 
	        3 把随机字符串以cookie形式返回给前端(存在浏览器的cookie中)
        -认证阶段:前端自动携带cookie到后端:sessionid:随机字符串
        -django.contrib.sessions.middleware.SessionMiddleware
        
    -自己写的,本质原理也是session的认证机制
    	-session是存储在服务端的键值对
        
   -认证类:接口需要登录后才能访问
	-1 写一个类,继承BaseAuthentication
    -2 重写authenticate
    -3 在方法中做认证---》取出前端传入的随机字符串--》去表中查出当前用户
    -4 返回两个值 user,token
    -5 后续的request.user就能拿到当前登录用户
    -6 使用:局部,全局
# 2 权限---》必须登录后才能用权限控制
	-1 写一个类,继承BasePermission
    -2 重写has_permission
    -3 在方法中做权限控制---》满足权限返回true,不满足返回false
    -4 使用:局部,全局
    
# 3 频率
	# 1 写一个类,继承SimpleRateThrottle
    # 2 重写get_cache_key,返回什么,就以什么做限制: IP地址,用户id限制
    	-request.META.get('REMOTE_ADDR')  客户端ip地址
    # 3 写一个类属性   scope = 'drf_day08'
    # 4 配置文件中配置
    '''
        'DEFAULT_THROTTLE_RATES': {
            'drf_day08': '3/m',  # 一分钟访问三次
        },
    '''

    # 5 局部使用,全局使用,局部禁用
    
    
    
# 4 排序--》查询所有接口---》GenericViewSet
	-配置类属性
        filter_backends = [OrderingFilter]
    	ordering_fields=['id','user_type']
		
	

session的认证机制图解

保存用户登录的状态:使用session, request.SESSION['name']='lin'
	1.生成一个随机字符串
    2.把数据存到django-session表中
    3.把随机字符串以cookie的形式返回给前端
    以上三件事是django的中间件做的
    django.contrib.sessions.middleware.SessionMiddleware

session的认证机制图解、 drf(过滤、分页、drf的异常处理方式)、补充(DateField和DateTimeField、auto_now_add和auto_now)_第1张图片

1 过滤

# 只针对于 查询所有接口
# 必须继承 GenericAPIView

# 安装:
	pip install django==3.2.12
    pip install django-filter
    
    
-使用方式:三种
	-方式一:内置的
    # 查询方式http://127.0.0.1:8000/books/?search=29  #模糊匹配: 只要名字中有29或价格中有29都能搜出来
    filter_backends = [SearchFilter, OrderingFilter]
    search_fields = ['name', 'price']	
    
    -方式二:第三方
    # http://127.0.0.1:8000/books/?name=红楼梦
    # http://127.0.0.1:8000/books/?price=19&name=西游记
    filter_backends = [DjangoFilterBackend]
    filterset_fields=['name','price']
    
    -方式三:自定义--完全自己控制
    # http://127.0.0.1:8000/books/?price=19&name=书
    filter_backends = [MyFilter]  # 我自己知道按哪些字段过滤
    # 需要写过滤类(下面)
    

代码演练

from rest_framework.filters import BaseFilterBackend
from django.db.models import Q


class MyFilter(BaseFilterBackend):
    def filter_queryset(self, request, queryset, view):
        # 基于queryset 进行过滤,过滤后返回即可
        # http://127.0.0.1:8000/books/?name=书   # 名字中有书的就查出来
        search_param = request.query_params.get('name')
        price = request.query_params.get('price')
        if search_param and price:
            # queryset = queryset.filter(Q(name__contains=search_param) | Q(price=price))  # qs对象的filter
            queryset = queryset.filter(name__contains=search_param,price=price)  # qs对象的filter
        return queryset

1.1 继承APIView写过滤和排序

#### 继承APIView 写过滤,写排序
class BookView(ViewSetMixin, APIView):
    def list(self, request, *args, **kwargs):
        # 按名字过滤
        print('asfdasdf')
        name = request.query_params.get('name')
        book_list = Book.objects.all().filter(name__contains=name)
        ser = BookSerializer(instance=book_list, many=True)
        return Response(ser.data)

1.2 继承GenericAPIView写过滤类,可以写多个

-写多个,他们是从左往右,依次执行
-大原则,配置多个过滤类的时候,第一个放尽量多个过滤掉数据
-配置多个:执行原理
	-先执行第一个过滤类的:filter_queryset返回qs对象
    -再执行第二个过滤类的filter_queryset,传入上一个返回的qs,过滤完返回qs对象
    

2 分页

只针对于 查询所有接口
	-分页展现形式:
    	web:下一页,下一页
    	小程序,app:上拉加载更多
        
        
#必须继承 GenericAPIView 

# 使用方式:三种分页方式--drf提供的
	1.方式一:基本分页  PageNumberPagination
		根据客户端请求自动对结果集进行分页,并返回包含分页信息的响应。
		客户端可以通过查询参数来控制分页,例如 ?page=2 表示请求第二页的数据。
	2.方式二:基本分页  LimitOffsetPagination
		客户端可以通过添加 ?limit 和 offset 查询参数来控制分页。
		是一种简单但有用的分页机制,适用于需要根据客户端需求精确控制分页结果的情况。
	3.方式三:基本分页  CursorPagination
		通过游标来获取分页数据。客户端可以使用 ?cursor 查询参数来控制游标位置,
	以获取下一页或上一页的数据。它是一个强大的分页机制,适用于需要处理大量数据的 API,
	特别是需要排序和过滤数据的情况。使用游标而不是页码来获取数据可以显著提高性能。
	

page.py

from rest_framework.pagination import LimitOffsetPagination, PageNumberPagination, CursorPagination


# 继承PageNumberPagination分页
class CommonPageNumberPagination(PageNumberPagination):
    # 过滤形式
    # http://api.example.org/accounts/?page=4
    # http://api.example.org/accounts/?page=4&page_size=100

    # 需要重写几个类属性
    page_size = 3  # 每页显示2条
    page_query_param = 'page'  # 指定第几页的 key 值
    page_size_query_param = 'size'  # 指定每页显示多少条
    max_page_size = 5  # 每页最多显示5条


# 继承LimitOffsetPagination分页
class CommonLimitOffsetPagination(LimitOffsetPagination):
    # 过滤形式
    # http://api.example.org/accounts/?limit=3  从开始取3条
    # http://api.example.org/accounts/?offset=4&limit=5  从第4条开始取5条
    default_limit = 2  # 默认每页显示3条
    limit_query_param = 'limit'  # 每页显示多少条的查询条件
    offset_query_param = 'offset'
    max_limit = 5


# 继承CursorPagination分页
class CommonCursorPagination(CursorPagination):
    # 只能上一条和下一条,不能指定跳转到中间的某页----》效率高,大数据
    cursor_query_param = 'cursor'  # 查询条件,用不到,需要有
    page_size = 2  # 每页显示2条
    ordering = 'id'  # 按id排序

视图类:继承GenericAPIView

from .page import CommonPageNumberPagination,CommonLimitOffsetPagination,CommonCursorPagination
class BookView(ViewSetMixin, ListAPIView):
    authentication_classes=[]
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    pagination_class =CommonCursorPagination   # 分页方式只有一种,配置一个类即可

继承APIView也要实现

class BookView(ViewSetMixin, APIView):
    authentication_classes=[]
    def list(self,request,*args,**kwargs):
        book_list=Book.objects.all()
        pagination =CommonPageNumberPagination()
        page=pagination.paginate_queryset(book_list,request)
        ser=BookSerializer(instance=page,many=True)
        return Response(ser.data)
        

3 异常处理

# 三大认证  视图类的方法中执行出错,都会被全局异常捕获
	-认证类,认证不通过,抛异常,前端看到没有问题,只是返回了提示信息---》处理了drf的异常
    
    
# drf全局异常处理,他会把drf的异常处理掉,统一返回格式,但是django原生的和python的都不会处理


# 我们要做的,无论什么异常,都返回固定格式
	1 写一个函数
    def common_exception(exc, context):
        # 执行一下原来的exception_handler---》它能处理drf的异常,我就不用处理了
        res = exception_handler(exc, context)
        if not res:  # 有值,说明是drf异常,它处理完了,没有值,是其他异常,我们自己处理
            return Response({'code': 999, 'msg': '非drf错误,错误信息是:%s' % str(exc)})
        else:
            return Response({'code': 888, 'msg': 'drf错误,错误信息是:' + res.data.get('detail')})
    2 配置文件配置
    	REST_FRAMEWORK = {
    	'EXCEPTION_HANDLER': 'app01.exceptions.common_exception', # 以后只要出了异常,都会走这个函数
	}

4 DateField和DateTimeField

DateField、DateTimeField
    auto_now_add=True    # 创建数据时自动添加当前时间
    auto_now=True           # 每次操作数据时更新为当前时间
    

`DateField` 和 `DateTimeField` 是 Django 中用于处理日期和日期时间的两个字段类型。

1. **DateField**:`DateField` 用于存储日期(年、月、日),不包括时间部分。通常用于需要记录事件、生日、日期等只关心日期部分的数据。在数据库中,它通常映射到日期字段,如 MySQL 中的 `DATE` 类型或 PostgreSQL 中的 `date` 类型。
   例如,在 Django 模型中定义一个 `DateField`:
   from django.db import models
   class Event(models.Model):
       event_date = models.DateField()

2. **DateTimeField**:`DateTimeField` 用于存储日期和时间,包括年、月、日、时、分、秒和毫秒。
   它用于需要记录精确的时间戳或日期时间的数据。在数据库中,它通常映射到日期时间字段,
   如 MySQL 中的 `DATETIME` 类型或 PostgreSQL 中的 `timestamp` 类型。

   例如,在 Django 模型中定义一个 `DateTimeField`:
   from django.db import models
   class LogEntry(models.Model):
       entry_datetime = models.DateTimeField()

在使用这两个字段类型时,您可以在 Django 模型中定义各种日期和日期时间属性,以满足您的需求。
这些字段允许您在应用程序中轻松存储和检索日期和日期时间数据。

5 auto_now_add和auto_now

在 Django 模型中,`auto_now_add` 和 `auto_now` 是两个用于自动管理日期和时间的属性,
通常用于 `DateTimeField` 字段。

1. **auto_now_add**:当一个对象被创建时,`auto_now_add` 属性会自动将该字段的值设置
  为对象的创建时间。它只会在对象创建时设置一次,之后不会再修改。
  这个属性通常用于记录对象的创建时间。

   例如,以下代码将在对象创建时自动记录创建时间:
   from django.db import models

   class Article(models.Model):
       title = models.CharField(max_length=100)
       content = models.TextField()
       created_at = models.DateTimeField(auto_now_add=True)


2. **auto_now**:无论对象何时被保存,`auto_now` 属性都会自动将该字段的值设置为当前时间。
  每次对象被保存时,这个字段的值都会被更新为当前时间。它通常用于记录对象的最后修改时间。

   例如,以下代码将在对象每次被保存时自动更新修改时间:
   from django.db import models

   class UserProfile(models.Model):
       user = models.OneToOneField(User, on_delete=models.CASCADE)
       last_modified = models.DateTimeField(auto_now=True)


总之,`auto_now_add` 用于记录对象的创建时间,而 `auto_now` 用于记录对象的最后修改时间。
这两个属性使得在模型中管理日期时间字段变得非常方便,无需手动处理这些时间戳。

你可能感兴趣的:(django,python01,django,python,restframework,分页,session,过滤,drf的异常处理)