注意:该文章部分摘抄之百度,仅当做学习笔记供小白使用,若侵权请联系删除!
显示关联表的数据,本示例会显示所有的关联的数据信息
- from rest_framework import serializers
- from .models import Student
- class StudentModelSerializer(serializers.ModelSerializer):
- class Meta:
- model = Student
- fields = "__all__"
读取到的结果器数据关联的为数字,此时需要进行一些操作可以读到正确数据
方法1: source='字段名.关联属性值'
- from rest_framework import serializers
- from drf_app import models
- # 文章的Serializer
- class ArticleSerializer(serializers.ModelSerializer):
- category = serializers.CharField(source='category.name')
- class Meta:
- model = models.Article
- fields = ['id','title','summary','content','category']
方法2 : 返回其属性值
- from rest_framework import serializers
- from . import models
-
-
- # 文章的Serializer
- class ArticleSerializer(serializers.ModelSerializer):
- category = serializers.SerializerMethodField()
-
- class Meta:
- model = models.Article
-
- fields = ['id', 'title', 'summary', 'content', 'category']
-
- def get_category(self, obj): # obj是表中的一行记录的对象
- return obj.category.name
显示choice类型字段的对应数据
- # 方法1
- status = serializers.CharField(source='get_status_display')
- # 方法2
- class Meta:
- def get_category(self,obj): #obj是表中的一行记录的对象
- return get_status_display()
认证&权限
权限选项:
- # 全局认证&权限配置
- REST_FRAMEWORK ={
- 'DEFAULT_AUTHENTICATION_CLASSES':(
- 'rest_framework.authentication.BasicAuthentication', # Basic 认证
- 'rest_framework.authentication.SessionAuthentication', # Session 认证
- ),
- 'DEFAULT_PERMISSION_CLASSES': (
- 'rest_framework.permission.IsAuthenticated' # 全局权限管理 登录的用户才可以访问
- ), # 若无此配置,默认所有用户可以访问,rest_framework.permission.AllowAny
- }
-
-
-
- # view 单个视图认证&权限
- from rest_framework.authentication import SessionAuthentication,BasicAuthentication
- from rest_framework.permissions import IsAuthenticated
- from rest_framework.views import APIView
-
- class MyView(APIView):
- # 指定认证的方式 # 401 未认证 403 权限被禁止
- authentication_classes = (SessionAuthentication,BasicAuthentication)
- permission_classes = (IsAuthenticated)
-
-
- # url 文件配置
-
- # DRF自带的登录接口认证
- path('api-auth/',include('rest_framework.urls')) # 登录接口的配置,已封装注销及登录接口
限流: 限制接口的访问频率,减少服务器的压力(反爬虫)
- REST_FRAMEWORK ={
- # 限流,全局默认配置
- 'DEFAULT_THROTTLE_CLASSES':[
- 'rest_framework.throttling.AnonRateThrottle',
- 'rest_framework.throttling.UserRateThrottle',
- ],
- # 设置用户的访问频率,局部用户限制,通过使用UserRateThrottle来限制用户的访问频率
- 'DEFAULT_THROTTLE_RATES': {
- # 时间周期 second/minute/hour/day
- 'anon':'10/day' , # 未认证的用户 10/day
- 'user':'1000/day' # 认证的用户 100/day
- }
- }
-
- # 局部配置调用视图view
- from rest_framework.throttling import UserRateThrottle
-
- class MyView(APIView):
- # 限流,限制用户的访问频率
- throttle_classes = (UserRateThrottle)
限流类型
全局配置
过滤:使用列表数据过滤字段信息,可使用django-fitlter扩展支持
pip install django-filter # 安装过滤器
- # 注册app
- 'django_filters'
-
- # 指定过滤器
- REST_FRAMEWORK = {
- 'DEFAULT_FILTER_BACKENDS':(
- 'django_filters.rest_framework.DjangoFilterBackend'
- )
- }
- # 方式1 自定义字段过滤
- filterset_fields = ('age',)
- # 方法2 自定义过滤类
- filterset_class = UserInfoFilter
-
- from app.models import UserInfo
- from django_filters import rest_framework as filters
- class UserInfoFilter(filters.FilterSet):
- """自定义过滤器类"""
- # 自定义字段过滤
- min_age = filters.NumberFilter(field_name='age',lookup_expr='gte')
- max_age = filters.NumberFilter(field_name='age',lookup_expr='lte')
- # 关联字段需要 关联字段__属性 实现
- name = filters.CharFilter(field_name='user__name')
- class Meta:
- model = UserInfo
- fields = ['name','age']
接口文档:DRF 自动生成网页版的接口文档,其生成的是继承APIView及其子类的视图
pip install coreapi # 安装依赖
- # setting 配置
- REST_FRAMEWORK = {
- # 接口文档配置
- 'DEFAULT_SCHEMA_CLASS':'rest_framework.schemas.coreapi.AutoSchema',
- }
-
- # url 配置
- from django.urls import path,include,re_path
- from rest_framework.documentation import include_docs_urls
- urlpatterns = [
- re_path(r'^docs/',include_docs_urls(title='接口文档'))
- ]
排序:DRF提供OrderingFilter可快速实现数据的指定方式排序
- # 局部信息配置
- serializer_class =xxxserializer
- filter_backends = [OrderingFilter] # 指定排序的过滤器
- ordering_fields = ('age''id') # 指定字段
-
- # 指定ordering参数字段对数据集进行排序 xxx/?ordering=age
-
- # 全局配置信息
- REST_FRAMEWORK = {
- # 指定过滤器
- 'DEFAULT_FILTER_BACKENDS':(
- # 指定django_filters的过滤器过滤
- 'django_filters.rest_framework.DjangoFilterBackend',
- # 指定DRF自带的排序过滤器来进行数据排序
- 'rest_framework.filters.OrderingFilter'
- ),
- }
分页:
- # 全局配置
- REST_FRAMEWORK = {
- # 分页 全局配置
- 'DEFAULT_PAGINATION_CLASS':'rest_frame.pagination.PageNumberPagination',
- 'PAGE_SIZE': 10 # 每页数据量
- }
-
- # 局部配置
-
- from rest_framework.pagination import PageNumberPagination
-
- class UserInfoPagination(PageNumberPagination):
- page_size = 5 # 每页数据量
- page_query_param = 'page' # 页面关键字参数,默认 'page'
- page_size_query_param = 'size' # 前端的每页面关键字参数 默认None
- max_page_size = 100 # 每页的数据量的最大值
-
- class MyView(APIView):
- """
- 局部配置,可通过pagination_class属性实现不同的分页器
- """
- pagination_class = UserInfoPagination
异常处理:
- # setting 配置
- REST_FRAMEWORK = {
- # 异常处理配置
- # 'EXCEPTION_HANDLER':'rest_framework.views.exception_handler',
- # 自定义异常的处理函数接口
- 'EXCEPTION_HANDLER':'common.exception.my_exception_handler',
- }
-
- # 自定义异常处理
- from rest_framework.views import exception_handler,Response,status
-
- def custom_exception_handler(exc,context):
- response = exception_handler(exc,context)
-
- if response is not None:
- response.data['status_code'] = response.status_code
- else:
- data ={'error':'服务器出错了'}
- response =Response(data,status=status.HTTP_500_INTERNAL_SERVER_ERROR)
- return response
文件上传:
- # model 配置
- class ImageModel(models.Model):
- # file = models.FileField() # 保存文件的字段
- file = models.ImageField() # 用于保存图片文件的字段
- class Meta:
- db_table = 'image'
- verbose_name = '图片'
-
- # serial 序列化
- from rest_framework import serializers
- from models import UserInfo,ImageModel
-
- class ImageSerializer(serializers.ModelSerializer):
- '图片关联序列化'
- class Meta:
- model = ImageModel
- fields = '__all__'
-
- #setting 配置
- # 指定文件上传存放的路径
- MEDIA_ROOT = BASE_DIR / 'image'
-
- # 指定文件url的路径
- MEDIA_URL = ''
-
-
- # view视图配置
-
- from .models import models,ImageModel
- from rest_framework.viewsets import ModelViewSet,mixins,GenericViewSet
-
-
- from .serializers import ImageSerializer
- class ImageView(mixins.CreateModelMixin,mixins.RetrieveModelMixin,
- mixins.ListModelMixin,GenericViewSet):
- queryset = ImageModel.objects.all()
- serializer_class = ImageSerializer
文件的上传和获取下载方式自定义优化
- from .models import models,ImageModel
- from rest_framework.viewsets import ModelViewSet,mixins,GenericViewSet
- from django.http import FileResponse
-
- from .serializers import ImageSerializer
- class ImageView(mixins.CreateModelMixin,mixins.RetrieveModelMixin,
- mixins.ListModelMixin,GenericViewSet):
- queryset = ImageModel.objects.all()
- serializer_class = ImageSerializer
- # 上传文件优化,限制文件的上传大小
- def create(self, request, *args, **kwargs):
- pic = request.data.get('files')
- size,name,type = pic.size,pic.name,pic.content_type
- if size>1024*30:
- return Response({'error':'图片不可以超过30kb'},status=status.HTTP_400_BAD_REQUEST)
- elif type not in ['image/png','image/jpg']:
- return Response({'error':'你上传的文件格式有问题'},status=status.HTTP_400_BAD_REQUEST)
- else:
- return super().create(request,*args,**kwargs)
- def retrieve(self, request, *args, **kwargs): # 照片获取下载
- pic = self.get_object()
- path = pic.files.path
- return FileResponse(open(path),'rb')
-
- def get_image(request,name):
- path = MEDIA_ROOT / name
- return FileResponse(open(path,'rb'))
-
-
- # url 配置
- urlpatterns = [
- re_path('image/(.+?)/',views.get_image)
- ]
跨域配置
- pip install django-cors-headers # 安装
-
- # 注册
- 'corsheaders'
-
- # 中间件设置注册
- 'corsheaders.middleware.CorsMiddleware',
-
-
- # 跨域白名单域名,可以访问后端接口
- CORS_ORIGIN_WHITELIST = (
- 'http://127.0.0.1:8080',
- 'http://localhost:8080'
- )
- CORS_ALLOW_CREDENTIALS = True # 在跨域访问中,后端是否支持允许携带cookie
JWT(Json Web Token) :主要流行的跨域请求方案
对于前后端分离的项目跨域请求时,不会自动携带cookie信息,而使用JWT认证机制
token 鉴权机制: cookie + session 鉴权,需要后端存储用户信息
JWT主要构成
simplejwt
- pip install djangorestframework-simplejwt # 安装
-
- # 注册应用
- 'rest_framework_simplejwt'
-
- # 配置setting
- REST_FRAMEWORK = {
- # DRF配置鉴权方式
- 'DEFAULT_AUTHENTICATION_CLASSES':(
- 'rest_framework_simplejwt.authentication.JWTAuthentication',
- ),
- }
-
- # url 配置
- from rest_framework_simplejwt.views import TokenVerifyView,TokenRefreshView,TokenObtainPairView
-
- urlpatterns = [
- path('login',TokenObtainPairView.as_view(),name='login'), # 登录
- path('token/refresh',TokenRefreshView.as_view(),name='token_refresh'), # token 刷新
- path('token/verify',TokenVerifyView.as_view(),name='token_verify'), # token 效验
- ]
JWT 的token 配置
- # JWT token 配置
- from datetime import timedelta
- SIMPLE_JWT = {
- "ACCESS_TOKEN_LIFETIME": timedelta(minutes=5), # 访问令牌的访问时间
- "REFRESH_TOKEN_LIFETIME": timedelta(days=1), # 刷新令牌的有效时间
- "ROTATE_REFRESH_TOKENS": False, # 若True 刷新后新的refresh_token又更新的有效时间
- "BLACKLIST_AFTER_ROTATION": False, # 若True 刷新后的token添加到黑名单中
- "UPDATE_LAST_LOGIN": False,
-
- "ALGORITHM": "HS256",
- "SIGNING_KEY": SECRET_KEY,
- "VERIFYING_KEY": "",
- "AUDIENCE": None,
- "ISSUER": None,
- "JSON_ENCODER": None,
- "JWK_URL": None,
- "LEEWAY": 0,
-
- "AUTH_HEADER_TYPES": ("Bearer",),
- "AUTH_HEADER_NAME": "HTTP_AUTHORIZATION",
- "USER_ID_FIELD": "id", # 唯一不变的数据库字段,包含在生成的令牌中以标识用户
- "USER_ID_CLAIM": "user_id",
- "USER_AUTHENTICATION_RULE": "rest_framework_simplejwt.authentication.default_user_authentication_rule",
-
- "AUTH_TOKEN_CLASSES": ("rest_framework_simplejwt.tokens.AccessToken",),
- "TOKEN_TYPE_CLAIM": "token_type",
- "TOKEN_USER_CLASS": "rest_framework_simplejwt.models.TokenUser",
-
- "JTI_CLAIM": "jti",
-
- "SLIDING_TOKEN_REFRESH_EXP_CLAIM": "refresh_exp",
- "SLIDING_TOKEN_LIFETIME": timedelta(minutes=5),
- "SLIDING_TOKEN_REFRESH_LIFETIME": timedelta(days=1),
-
- "TOKEN_OBTAIN_SERIALIZER": "rest_framework_simplejwt.serializers.TokenObtainPairSerializer",
- "TOKEN_REFRESH_SERIALIZER": "rest_framework_simplejwt.serializers.TokenRefreshSerializer",
- "TOKEN_VERIFY_SERIALIZER": "rest_framework_simplejwt.serializers.TokenVerifySerializer",
- "TOKEN_BLACKLIST_SERIALIZER": "rest_framework_simplejwt.serializers.TokenBlacklistSerializer",
- "SLIDING_TOKEN_OBTAIN_SERIALIZER": "rest_framework_simplejwt.serializers.TokenObtainSlidingSerializer",
- "SLIDING_TOKEN_REFRESH_SERIALIZER": "rest_framework_simplejwt.serializers.TokenRefreshSlidingSerializer",
- }
自定义类登录认证
- from rest_framework_simplejwt.views import TokenObtainPairView
-
- class MyLoginTokenObtainPairView(TokenObtainPairView):
- def post(self, request, *args, **kwargs):
- serializer = self.get_serializer(data=request.data)
- try:
- serializer.is_valid(raise_exception=True)
- except TokenError as e:
- raise InvalidToken(e.args[0])
- # 自定义登录成功后返回的数据信息
- result = serializer.validated_data
- result['email'] = serializer.user.email
- result['username'] = serializer.user.username
- result['id'] = serializer.user.id
- result['token'] = result.pop('access')
- return Response(serializer.validated_data, status=status.HTTP_200_OK)
自定义令牌声明:访问官方文档地址如下
Creating tokens manually — Simple JWT 5.2.2.post30+gfaf92e8 documentation
- # 自定义类
- from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
- from rest_framework_simplejwt.views import TokenObtainPairView
-
- class MyTokenObtainPairSerializer(TokenObtainPairSerializer):
- @classmethod
- def get_token(cls, user):
- token = super().get_token(user)
-
- # Add custom claims
- token['name'] = user.name
- # ...
-
- return token
-
- # 配置setting
- SIMPLE_JWT = {
- # It will work instead of the default serializer(TokenObtainPairSerializer).
- "TOKEN_OBTAIN_SERIALIZER": "my_app.serializers.MyTokenObtainPairSerializer",
- # ...
- }
手动创建令牌
- from rest_framework_simplejwt.tokens import RefreshToken
-
- def get_tokens_for_user(user):
- refresh = RefreshToken.for_user(user)
-
- return {
- 'refresh': str(refresh),
- 'access': str(refresh.access_token),
- }