• DRF序列化、认证、跨域问题


    初级

    #models.py
    from django.db import models
    class User(models.Model):
        user = models.CharField(max_length=32)
        password = models.CharField(max_length=32)
        user_detail = models.OneToOneField(to='UserDetail', on_delete=models.SET_NULL, null=True, db_constraint=False)
    
        def account_msg(self):
            return self.user + ":" + self.password
    class UserDetail(models.Model):
        phone_num = models.CharField(max_length=11)
        info = models.TextField()
        
    # 自定义序列化类:为具体的类提供序列化
    # objectjson.py
    from rest_framework import serializers
    class UserJson(serializers.Serializer):
        id = serializers.IntegerField()
        name = serializers.CharField(source='user')
        password = serializers.CharField()
        account = serializers.CharField(source='account_msg')
        # user_detail = serializers.CharField()
        # user_phone_num = serializers.CharField(source='user_detail.phone_num')
        detail = serializers.SerializerMethodField()
        def get_detail(self, object):
            return {'phone': object.user_detail.phone_num, 'info': object.user_detail.info}#自定义返回的数据格式
          
    #views.py
    from rest_framework.views import APIView
    from rest_framework.response import Response
    from app import objectjson, models
    class Users(APIView):
        def get(self, request):
            user_list = models.User.objects.all()
            user_data = objectjson.UserJson(user_list, many=True).data
            return Response({
                'status': 0,
                'message': 'ok',
                'results': user_data
            })
    
    #urls.py
    urlpatterns = [
        url(r'^users/', views.Users.as_view()),
    ]

    高级

    #models.py
    class Book(models.Model):
        name = models.CharField(max_length=20)
        price = models.DecimalField(max_digits=5, decimal_places=2)
        author = models.ManyToManyField('Author', db_constraint=False)
    class Author(models.Model):
        name = models.CharField(max_length=20)
        author_detail = models.OneToOneField(to='AuthorDetail', on_delete=models.SET_NULL, null=True, db_constraint=False)
    class AuthorDetail(models.Model):
        age = models.IntegerField()
        telephone = models.BigIntegerField()
    # 自定义序列化类:为具体的类提供序列化
    # objectjson.py
    class AuthorDetailJson(serializers.ModelSerializer):
        class Meta:
            model = models.AuthorDetail
            # fields ='__all__' #对外提供所有字段
            exclude = ['id']  # 和fields两者取一,代表除id字段不提供
    class AuthorJson(serializers.ModelSerializer):
        class Meta:
            model = models.Author
            fields = ['id', 'name', 'detail']  # 自定义的detail字段也要声明也要提供哪些字段
            # fields = '__all__'
        detail = serializers.SerializerMethodField()
        # exclude = ['author_detail']
        def get_detail(self, object):
            detail_data = AuthorDetailJson(object.author_detail).data
            return detail_data
    class BookJson(serializers.ModelSerializer):
        class Meta:
            model = models.Book
            exclude = ['author']
            # fields = '__all__'
            # depth = 2
        authors = serializers.SerializerMethodField()
        def get_authors(self, object):
            author_list = object.author.all()
            author_data = AuthorJson(author_list, many=True).data
            return author_data
     #views.py
    class Books(APIView):
        def get(self, request):
            book_list = models.Book.objects.all()
            book_data = objectjson.BookJson(book_list, many=True).data
            return Response({
                'status': 0,
                'message': 'ok',
                'results': book_data
            })
      
    #urls.py
    urlpatterns = [
        url(r'^books/', views.Books.as_view()),
    ]

    校验

    # objectjson.py
    class BookJson(serializers.ModelSerializer):
        class Meta:
            model = models.Book
            fields = '__all__'
            #单个字段校验
        name = serializers.CharField(min_length=3, max_length=5, error_messages=
        {
            'min_length': '太短了', 'max_length': '太长了'
        })
    
        # 局部钩子
        def validate_name(self, value):
            from rest_framework.exceptions import ValidationError
            book_object = models.Book.objects.filter(name=value)
            if book_object:
                raise ValidationError('书名已经存在')
            if 'sb' in value:
                raise ValidationError('不能出现敏感词汇')
            return value
    # views.py
    class Books(APIView):
        def post(self, request):
            book = request.data
            book_json = objectjson.BookJson(data=book)  # 必须明确data
            if book_json.is_valid():
                book_json.save()
                return Response({
                    'status': 0,
                    'message': 'ok',
                    'results': book_json.data
                })
            return Response({
                'status': 1,
                'msg': book_json.errors
            })

    全局钩子

    # 全局钩子校验
    def validate(self, attrs):
        from rest_framework.exceptions import ValidationError
        pwd = attrs.get('pwd')
        re_pwd = attrs.get('re_pwd')
        if pwd == re_pwd:
            return attrs
        else:
            raise ValidationError('密码校验失败')
    了解

    数据删改查

    # views.py
    class Book(APIView):
        def get(self, request, id):
            book = models.Book.objects.filter(pk=id).first()
            book_data = objson.BookJson(book).data
            return Response({
                'status': 0,
                'msg': 'ok',
                'results': book_data
            })
    
        def put(self, request, id):
            book = models.Book.objects.filter(pk=id).first()
            book_json = objson.BookJson(data=request.data, instance=book)  # 通过instance标识修改的对象
            if book_json.is_valid():
                book_json.save()  # 同样用save更新到数据库
                return Response({
                    'status': 0,
                    'msg': 'ok',
                    'results': book_json.data
                })
            return Response({
                'status': 1,
                'msg': book_json.errors,
            })
    
        def delete(self,request,id):
            models.Book.objects.filter(pk=id).delete()  # 删除操作直接用ORM操作数据库
            return Response({
                'status': 2,
                'msg': 'delete success',
            })

    基于ORM操作增删改

    class Books(APIView):
      #获取所有书籍
        def get(self, request):
            book_list = models.Book.objects.all()
            book_data = objectjson.BookJson(book_list, many=True).data
            return Response({
                'status': 0,
                'message': 'ok',
                'results': book_data
            })
            #增加书籍
        def post(self, request):
            name = request.data.get('name')
            price = request.data.get('price')
            author = request.data.get('author')
            book_object = models.Book.objects.create(name=name, price=price)
            book_object.author.add(*author)
            book_data = objectjson.BookJson(book_object).data
            return Response({
                'status': 0,
                'message': 'ok',
                'results': book_data
            })
          
          
    class Book(APIView):
      #获取一本书籍
        def get(self, request, id):
            book = models.Book.objects.filter(pk=id).first()
            book_data = objectjson.BookJson(book).data
            return Response({
                'status': 0,
                'message': 'ok',
                'results': book_data
            })
            #修改书籍
        def put(self, request, id):
            book_object = models.Book.objects.filter(pk=id).first()  # type:models.Book
            name = request.data.get('name')
            price = request.data.get('price')
            author = request.data.get('author')
            book_object.name = name
            book_object.price = price
            book_object.author = author
            book_object.save()
            book_data = objectjson.BookJson(book_object).data
            return Response({
                'status': 0,
                'message': 'ok',
                'results': book_data
            })
            #删除书籍
        def delete(self, request, id):
            models.Book.objects.filter(pk=id).delete()
            return Response({
                'status': 0,
                'message': 'ok',
                'results': 'delete success'
            })

    Django跨域问题

    什么是跨域

    '''
    通常情况下,A网站访问B服务器资源时,不满足以下三个条件其一就是跨域访问
    1.协议不同
    2.端口不同
    3.主机不同
    '''

    Django解决跨域

    '''
    安装django-cors-headers模块
    
    在settings.py中配置
    # 注册app
    INSTALLED_APPS =[
        ...
        'corsheaders'
    ]
    #添加中间件
    MIDDLEWARE = [
        ...
        'corsheaders.middleware.CorsMiddleware'
    ]
    #允许跨域源
    CORS_ORIGIN_ALLOW_ALL = True
    '''

    认证组件

    # views.py
    
    class Auth:
          def authenticate(self,request):
              #完全具备认证功能
            pass
    class Book(APIView):
          authentication_classes = [Auth,]

    认证源码流程

    """
    1.views.Books.as_view()2.view = super(APIView, cls).as_view(**initkwargs)  分发给dispatch
    3.def dispatch(self, request, *args, **kwargs):  
    4. 
    request = self.initialize_request(request, *args, **kwargs) 封装request
    self.initial(request, *args, **kwargs)  三大认证
    5.self.perform_authentication(request) 转向Request类的user
    6.request.py的Request的user  self._authenticate()
    7.self.authenticators  self是drf的request对象
    8.drf的request对象的init方法 authenticators是初始化参数
    9.在哪初始化的: request = def initialize_request(self, request, *args, **kwargs)
    10.self.get_authenticators() 需要 self.authentication_classes
    11.self代表APIView类或子类对象,在自定义Books(APIView)中提供
    """
  • 相关阅读:
    错位排序
    不容易系列之(4)——考新郎
    大数乘法
    神、上帝以及老天爷(错位排序)
    学生成绩……
    蛇形矩阵
    topcoder
    进制转换
    问题 1011
    topcoder 针对C程序员的TopCoder C++ (快速掌握)_ixigua—仅有杀毒软件是不够的…… .
  • 原文地址:https://www.cnblogs.com/ShenJunHui6/p/10878814.html
Copyright © 2020-2023  润新知