• django rest framework 学习笔记2


    注意:该文章部分摘抄之百度,仅当做学习笔记供小白使用,若侵权请联系删除!


    显示关联表的数据,本示例会显示所有的关联的数据信息

    1. from rest_framework import serializers
    2. from .models import Student
    3. class StudentModelSerializer(serializers.ModelSerializer):
    4. class Meta:
    5. model = Student
    6. fields = "__all__"

    读取到的结果器数据关联的为数字,此时需要进行一些操作可以读到正确数据

    方法1: source='字段名.关联属性值'

    1. from rest_framework import serializers
    2. from drf_app import models
    3. # 文章的Serializer
    4. class ArticleSerializer(serializers.ModelSerializer):
    5. category = serializers.CharField(source='category.name')
    6. class Meta:
    7. model = models.Article
    8. fields = ['id','title','summary','content','category']

    方法2 : 返回其属性值

    1. from rest_framework import serializers
    2. from . import models
    3. # 文章的Serializer
    4. class ArticleSerializer(serializers.ModelSerializer):
    5. category = serializers.SerializerMethodField()
    6. class Meta:
    7. model = models.Article
    8. fields = ['id', 'title', 'summary', 'content', 'category']
    9. def get_category(self, obj): # obj是表中的一行记录的对象
    10. return obj.category.name

    显示choice类型字段的对应数据

    1. # 方法1
    2. status = serializers.CharField(source='get_status_display')
    3. # 方法2
    4. class Meta:
    5. def get_category(self,obj): #obj是表中的一行记录的对象
    6. return get_status_display()

    认证&权限

    权限选项:

    • AllowAny           # 容许所有用户
    • IsAuthenticated   #  仅通过认证的用户
    • IsAdminUser      #  仅管理员用户
    • IsAuthenticatedOrReadOnly  #  只有认证的用户可以完全操作,其他可以可读
    1. # 全局认证&权限配置
    2. REST_FRAMEWORK ={
    3. 'DEFAULT_AUTHENTICATION_CLASSES':(
    4. 'rest_framework.authentication.BasicAuthentication', # Basic 认证
    5. 'rest_framework.authentication.SessionAuthentication', # Session 认证
    6. ),
    7. 'DEFAULT_PERMISSION_CLASSES': (
    8. 'rest_framework.permission.IsAuthenticated' # 全局权限管理 登录的用户才可以访问
    9. ), # 若无此配置,默认所有用户可以访问,rest_framework.permission.AllowAny
    10. }
    11. # view 单个视图认证&权限
    12. from rest_framework.authentication import SessionAuthentication,BasicAuthentication
    13. from rest_framework.permissions import IsAuthenticated
    14. from rest_framework.views import APIView
    15. class MyView(APIView):
    16. # 指定认证的方式 # 401 未认证 403 权限被禁止
    17. authentication_classes = (SessionAuthentication,BasicAuthentication)
    18. permission_classes = (IsAuthenticated)
    19. # url 文件配置
    20. # DRF自带的登录接口认证
    21. path('api-auth/',include('rest_framework.urls')) # 登录接口的配置,已封装注销及登录接口

    限流: 限制接口的访问频率,减少服务器的压力(反爬虫)

    1. REST_FRAMEWORK ={
    2. # 限流,全局默认配置
    3. 'DEFAULT_THROTTLE_CLASSES':[
    4. 'rest_framework.throttling.AnonRateThrottle',
    5. 'rest_framework.throttling.UserRateThrottle',
    6. ],
    7. # 设置用户的访问频率,局部用户限制,通过使用UserRateThrottle来限制用户的访问频率
    8. 'DEFAULT_THROTTLE_RATES': {
    9. # 时间周期 second/minute/hour/day
    10. 'anon':'10/day' , # 未认证的用户 10/day
    11. 'user':'1000/day' # 认证的用户 100/day
    12. }
    13. }
    14. # 局部配置调用视图view
    15. from rest_framework.throttling import UserRateThrottle
    16. class MyView(APIView):
    17. # 限流,限制用户的访问频率
    18. throttle_classes = (UserRateThrottle)

    限流类型

    • AnonRateThrottle 
      • 限制所有匿名未认证的用户,使用IP区分
      • 使用DEFAULT_THROTTLE_RATES['anon'] 来设置频率
    • UserRateThrottle
      • 限制认证用户,使用用户ID区分
      • 使用DEFAULT_THROTTLE_RATES['anon'] 来设置频率
    • ScopedRateThrottle
      • 限制用户对于具体视图的访问频率,使用IP或ID区分
      • 视图中使用throttle_scope 制定频率

    全局配置

    • DEFAULT_THROTTLE_CLASSES: 设置限流类型
    • DEFAULT_THROTTLE_RATES: 设置限制的频率

    过滤:使用列表数据过滤字段信息,可使用django-fitlter扩展支持

    pip install  django-filter #  安装过滤器
    1. # 注册app
    2. 'django_filters'
    3. # 指定过滤器
    4. REST_FRAMEWORK = {
    5. 'DEFAULT_FILTER_BACKENDS':(
    6. 'django_filters.rest_framework.DjangoFilterBackend'
    7. )
    8. }
    1. # 方式1 自定义字段过滤
    2. filterset_fields = ('age',)
    3. # 方法2 自定义过滤类
    4. filterset_class = UserInfoFilter
    5. from app.models import UserInfo
    6. from django_filters import rest_framework as filters
    7. class UserInfoFilter(filters.FilterSet):
    8. """自定义过滤器类"""
    9. # 自定义字段过滤
    10. min_age = filters.NumberFilter(field_name='age',lookup_expr='gte')
    11. max_age = filters.NumberFilter(field_name='age',lookup_expr='lte')
    12. # 关联字段需要 关联字段__属性 实现
    13. name = filters.CharFilter(field_name='user__name')
    14. class Meta:
    15. model = UserInfo
    16. fields = ['name','age']

    接口文档:DRF 自动生成网页版的接口文档,其生成的是继承APIView及其子类的视图

    pip install  coreapi # 安装依赖
    
    1. # setting 配置
    2. REST_FRAMEWORK = {
    3. # 接口文档配置
    4. 'DEFAULT_SCHEMA_CLASS':'rest_framework.schemas.coreapi.AutoSchema',
    5. }
    6. # url 配置
    7. from django.urls import path,include,re_path
    8. from rest_framework.documentation import include_docs_urls
    9. urlpatterns = [
    10. re_path(r'^docs/',include_docs_urls(title='接口文档'))
    11. ]

    排序:DRF提供OrderingFilter可快速实现数据的指定方式排序

    1. # 局部信息配置
    2. serializer_class =xxxserializer
    3. filter_backends = [OrderingFilter] # 指定排序的过滤器
    4. ordering_fields = ('age''id') # 指定字段
    5. # 指定ordering参数字段对数据集进行排序 xxx/?ordering=age
    6. # 全局配置信息
    7. REST_FRAMEWORK = {
    8. # 指定过滤器
    9. 'DEFAULT_FILTER_BACKENDS':(
    10. # 指定django_filters的过滤器过滤
    11. 'django_filters.rest_framework.DjangoFilterBackend',
    12. # 指定DRF自带的排序过滤器来进行数据排序
    13. 'rest_framework.filters.OrderingFilter'
    14. ),
    15. }

    分页:

    1. # 全局配置
    2. REST_FRAMEWORK = {
    3. # 分页 全局配置
    4. 'DEFAULT_PAGINATION_CLASS':'rest_frame.pagination.PageNumberPagination',
    5. 'PAGE_SIZE': 10 # 每页数据量
    6. }
    7. # 局部配置
    8. from rest_framework.pagination import PageNumberPagination
    9. class UserInfoPagination(PageNumberPagination):
    10. page_size = 5 # 每页数据量
    11. page_query_param = 'page' # 页面关键字参数,默认 'page'
    12. page_size_query_param = 'size' # 前端的每页面关键字参数 默认None
    13. max_page_size = 100 # 每页的数据量的最大值
    14. class MyView(APIView):
    15. """
    16. 局部配置,可通过pagination_class属性实现不同的分页器
    17. """
    18. pagination_class = UserInfoPagination

    异常处理:

    1. # setting 配置
    2. REST_FRAMEWORK = {
    3. # 异常处理配置
    4. # 'EXCEPTION_HANDLER':'rest_framework.views.exception_handler',
    5. # 自定义异常的处理函数接口
    6. 'EXCEPTION_HANDLER':'common.exception.my_exception_handler',
    7. }
    8. # 自定义异常处理
    9. from rest_framework.views import exception_handler,Response,status
    10. def custom_exception_handler(exc,context):
    11. response = exception_handler(exc,context)
    12. if response is not None:
    13. response.data['status_code'] = response.status_code
    14. else:
    15. data ={'error':'服务器出错了'}
    16. response =Response(data,status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    17. return response

     文件上传:

    • ImageField   # 上传图片
    • FileField       #  上传文件
    1. # model 配置
    2. class ImageModel(models.Model):
    3. # file = models.FileField() # 保存文件的字段
    4. file = models.ImageField() # 用于保存图片文件的字段
    5. class Meta:
    6. db_table = 'image'
    7. verbose_name = '图片'
    8. # serial 序列化
    9. from rest_framework import serializers
    10. from models import UserInfo,ImageModel
    11. class ImageSerializer(serializers.ModelSerializer):
    12. '图片关联序列化'
    13. class Meta:
    14. model = ImageModel
    15. fields = '__all__'
    16. #setting 配置
    17. # 指定文件上传存放的路径
    18. MEDIA_ROOT = BASE_DIR / 'image'
    19. # 指定文件url的路径
    20. MEDIA_URL = ''
    21. # view视图配置
    22. from .models import models,ImageModel
    23. from rest_framework.viewsets import ModelViewSet,mixins,GenericViewSet
    24. from .serializers import ImageSerializer
    25. class ImageView(mixins.CreateModelMixin,mixins.RetrieveModelMixin,
    26. mixins.ListModelMixin,GenericViewSet):
    27. queryset = ImageModel.objects.all()
    28. serializer_class = ImageSerializer

    文件的上传和获取下载方式自定义优化

    1. from .models import models,ImageModel
    2. from rest_framework.viewsets import ModelViewSet,mixins,GenericViewSet
    3. from django.http import FileResponse
    4. from .serializers import ImageSerializer
    5. class ImageView(mixins.CreateModelMixin,mixins.RetrieveModelMixin,
    6. mixins.ListModelMixin,GenericViewSet):
    7. queryset = ImageModel.objects.all()
    8. serializer_class = ImageSerializer
    9. # 上传文件优化,限制文件的上传大小
    10. def create(self, request, *args, **kwargs):
    11. pic = request.data.get('files')
    12. size,name,type = pic.size,pic.name,pic.content_type
    13. if size>1024*30:
    14. return Response({'error':'图片不可以超过30kb'},status=status.HTTP_400_BAD_REQUEST)
    15. elif type not in ['image/png','image/jpg']:
    16. return Response({'error':'你上传的文件格式有问题'},status=status.HTTP_400_BAD_REQUEST)
    17. else:
    18. return super().create(request,*args,**kwargs)
    19. def retrieve(self, request, *args, **kwargs): # 照片获取下载
    20. pic = self.get_object()
    21. path = pic.files.path
    22. return FileResponse(open(path),'rb')
    23. def get_image(request,name):
    24. path = MEDIA_ROOT / name
    25. return FileResponse(open(path,'rb'))
    26. # url 配置
    27. urlpatterns = [
    28. re_path('image/(.+?)/',views.get_image)
    29. ]

    跨域配置

    1. pip install django-cors-headers # 安装
    2. # 注册
    3. 'corsheaders'
    4. # 中间件设置注册
    5. 'corsheaders.middleware.CorsMiddleware',
    6. # 跨域白名单域名,可以访问后端接口
    7. CORS_ORIGIN_WHITELIST = (
    8. 'http://127.0.0.1:8080',
    9. 'http://localhost:8080'
    10. )
    11. CORS_ALLOW_CREDENTIALS = True # 在跨域访问中,后端是否支持允许携带cookie

    JWT(Json  Web Token) :主要流行的跨域请求方案

    对于前后端分离的项目跨域请求时,不会自动携带cookie信息,而使用JWT认证机制

    token 鉴权机制:  cookie + session 鉴权,需要后端存储用户信息

    JWT主要构成

    • header: 包含类型+加密算法 {" typ" : "JWT" , "alg":"Hs256"},进行base64 加密
    • payload    包含主要内容部分,存放一些有效信息,主要字段
      • iss :  签发者
      • sub:  面向的用户
      • aud:  接收的一方
      • exp:  过期时间,时间戳
      • at:     签发时间
    • signature:使用编码后的header、payload及提供的密钥,再使用指定的签名算法进行签名,保证JWT没有被篡改过(加密[header+payload]+私钥secret---加密算法形成)主要包含三部分:
      • header  (base64编码)
      • payload (base64编码)
      • secret  (私钥)

    simplejwt

    1. pip install djangorestframework-simplejwt # 安装
    2. # 注册应用
    3. 'rest_framework_simplejwt'
    4. # 配置setting
    5. REST_FRAMEWORK = {
    6. # DRF配置鉴权方式
    7. 'DEFAULT_AUTHENTICATION_CLASSES':(
    8. 'rest_framework_simplejwt.authentication.JWTAuthentication',
    9. ),
    10. }
    11. # url 配置
    12. from rest_framework_simplejwt.views import TokenVerifyView,TokenRefreshView,TokenObtainPairView
    13. urlpatterns = [
    14. path('login',TokenObtainPairView.as_view(),name='login'), # 登录
    15. path('token/refresh',TokenRefreshView.as_view(),name='token_refresh'), # token 刷新
    16. path('token/verify',TokenVerifyView.as_view(),name='token_verify'), # token 效验
    17. ]

    JWT 的token 配置

    1. # JWT token 配置
    2. from datetime import timedelta
    3. SIMPLE_JWT = {
    4. "ACCESS_TOKEN_LIFETIME": timedelta(minutes=5), # 访问令牌的访问时间
    5. "REFRESH_TOKEN_LIFETIME": timedelta(days=1), # 刷新令牌的有效时间
    6. "ROTATE_REFRESH_TOKENS": False, # 若True 刷新后新的refresh_token又更新的有效时间
    7. "BLACKLIST_AFTER_ROTATION": False, # 若True 刷新后的token添加到黑名单中
    8. "UPDATE_LAST_LOGIN": False,
    9. "ALGORITHM": "HS256",
    10. "SIGNING_KEY": SECRET_KEY,
    11. "VERIFYING_KEY": "",
    12. "AUDIENCE": None,
    13. "ISSUER": None,
    14. "JSON_ENCODER": None,
    15. "JWK_URL": None,
    16. "LEEWAY": 0,
    17. "AUTH_HEADER_TYPES": ("Bearer",),
    18. "AUTH_HEADER_NAME": "HTTP_AUTHORIZATION",
    19. "USER_ID_FIELD": "id", # 唯一不变的数据库字段,包含在生成的令牌中以标识用户
    20. "USER_ID_CLAIM": "user_id",
    21. "USER_AUTHENTICATION_RULE": "rest_framework_simplejwt.authentication.default_user_authentication_rule",
    22. "AUTH_TOKEN_CLASSES": ("rest_framework_simplejwt.tokens.AccessToken",),
    23. "TOKEN_TYPE_CLAIM": "token_type",
    24. "TOKEN_USER_CLASS": "rest_framework_simplejwt.models.TokenUser",
    25. "JTI_CLAIM": "jti",
    26. "SLIDING_TOKEN_REFRESH_EXP_CLAIM": "refresh_exp",
    27. "SLIDING_TOKEN_LIFETIME": timedelta(minutes=5),
    28. "SLIDING_TOKEN_REFRESH_LIFETIME": timedelta(days=1),
    29. "TOKEN_OBTAIN_SERIALIZER": "rest_framework_simplejwt.serializers.TokenObtainPairSerializer",
    30. "TOKEN_REFRESH_SERIALIZER": "rest_framework_simplejwt.serializers.TokenRefreshSerializer",
    31. "TOKEN_VERIFY_SERIALIZER": "rest_framework_simplejwt.serializers.TokenVerifySerializer",
    32. "TOKEN_BLACKLIST_SERIALIZER": "rest_framework_simplejwt.serializers.TokenBlacklistSerializer",
    33. "SLIDING_TOKEN_OBTAIN_SERIALIZER": "rest_framework_simplejwt.serializers.TokenObtainSlidingSerializer",
    34. "SLIDING_TOKEN_REFRESH_SERIALIZER": "rest_framework_simplejwt.serializers.TokenRefreshSlidingSerializer",
    35. }

    自定义类登录认证

    1. from rest_framework_simplejwt.views import TokenObtainPairView
    2. class MyLoginTokenObtainPairView(TokenObtainPairView):
    3. def post(self, request, *args, **kwargs):
    4. serializer = self.get_serializer(data=request.data)
    5. try:
    6. serializer.is_valid(raise_exception=True)
    7. except TokenError as e:
    8. raise InvalidToken(e.args[0])
    9. # 自定义登录成功后返回的数据信息
    10. result = serializer.validated_data
    11. result['email'] = serializer.user.email
    12. result['username'] = serializer.user.username
    13. result['id'] = serializer.user.id
    14. result['token'] = result.pop('access')
    15. return Response(serializer.validated_data, status=status.HTTP_200_OK)

    自定义令牌声明:访问官方文档地址如下

    Creating tokens manually — Simple JWT 5.2.2.post30+gfaf92e8 documentation

    1. # 自定义类
    2. from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
    3. from rest_framework_simplejwt.views import TokenObtainPairView
    4. class MyTokenObtainPairSerializer(TokenObtainPairSerializer):
    5. @classmethod
    6. def get_token(cls, user):
    7. token = super().get_token(user)
    8. # Add custom claims
    9. token['name'] = user.name
    10. # ...
    11. return token
    12. # 配置setting
    13. SIMPLE_JWT = {
    14. # It will work instead of the default serializer(TokenObtainPairSerializer).
    15. "TOKEN_OBTAIN_SERIALIZER": "my_app.serializers.MyTokenObtainPairSerializer",
    16. # ...
    17. }

    手动创建令牌

    1. from rest_framework_simplejwt.tokens import RefreshToken
    2. def get_tokens_for_user(user):
    3. refresh = RefreshToken.for_user(user)
    4. return {
    5. 'refresh': str(refresh),
    6. 'access': str(refresh.access_token),
    7. }
  • 相关阅读:
    【python】Sklearn—Cluster
    将 mixamo 中的动画重定向到 UE 的小白人中
    UA硬件安装环境
    安卓逆向入门级学习————自用
    sq练习2
    locust的使用
    Apache Doris 在小鹅通的应用实践
    二进制安装docker
    使用Python实现文字的声音播放
    基于51单片机霍尔传感器测速(仿真+源程序)
  • 原文地址:https://blog.csdn.net/qq_44238024/article/details/136166843