zoukankan      html  css  js  c++  java
  • drf-day5——权限,频率,异常处理

    作业:

    1 视图类继承GenericAPIView,get方法,post方法,用的序列化类不一样

    # 1 路由ulrs.py:
    from app01 import views
    urlpatterns = [
        path('books/', views.BookView.as_view()),
    ]
    
    
    
    
    
    # 2 视图views.py
    from app01.ser import GetBookSerializer, CreateBookSerializer
    from rest_framework.exceptions import MethodNotAllowed
    from rest_framework.response import Response
    from app01.models import Book
    from rest_framework.generics import GenericAPIView
    
    class BookView(GenericAPIView):
        queryset = Book.objects
    
        def get_serializer_class(self):
            if self.request.method == 'GET':
                return GetBookSerializer
            elif self.request.method == 'POST':
                return CreateBookSerializer
            else: 
                raise MethodNotAllowed(self.request.method)
    
        def get(self, request):
            book_list = self.get_queryset()
            book_ser = self.get_serializer(book_list, many=True)
            return Response(book_ser.data)
    
        def post(self, request):
            book_ser = self.get_serializer(data=request.data)
            if book_ser.is_valid():
                book_ser.save()
                return Response(book_ser.data)
            else:
                return Response({'status': 101, 'msg': book_ser.errors})
            
            
    
    
            
    # 3 序列化类
    class CreateBookSerializer(serializers.Serializer):
        id = serializers.IntegerField(read_only=True)
        name = serializers.CharField(max_length=8, min_length=2)
        price = serializers.DecimalField(max_digits=8, decimal_places=2)
        publish = serializers.CharField(max_length=18, min_length=4)
    
        def validate_name(self, data):
            if 'xxx' in data or 'sb' in data:
                raise ValidationError(f'创建的图书;{data},书名中有:xxx/sb 敏感词')
            else:
                return data
    
        def validate(self, validate_data):
            name = validate_data.get('name')
            book = Book.objects.filter(name=name)
            if book:
                raise ValidationError(f'图书{name}已存在')
            return validate_data
    
        def create(self, validated_data):
            print(type(validated_data.get('price')), validated_data.get('price'))
            instance = Book.objects.create(**validated_data)
            return instance
    
    
    class GetBookSerializer(serializers.ModelSerializer):
        class Meta:
            model = Book
            fields = '__all__'
    
    

    数据:

    image-20200712210812597

    效果:

    1.GET获取所有图书

    image-20200712211043538

    2 . POST创建带有敏感词的数据:

    image-202007122130475063. POST创建一本已存在的书籍

    image-20200712213240514

    4.正常创建

    image-20200712213437512

    2 图书一堆关联表的增删查改写完book表,author表,authordetail表,publish表,中间表

    2.1 路由urls.py

    from django.contrib import admin
    from django.urls import path, re_path
    from app01 import views
    
    urlpatterns = [
        path('admin/', admin.site.urls),
    
        # 1 图书增删改查
        re_path('^books/(?P<pk>d+)',
                views.BookView.as_view(actions={'get': 'retrieve', 'put': 'update', 'delete': 'destroy'})),
        path('books/', views.BookView.as_view(actions={'post': 'create', 'get': 'list'})),
    
        # 2 作者增删改查
        re_path('^authors/(?P<pk>d+)',
                views.AuthorView.as_view(actions={'get': 'retrieve', 'put': 'update', 'delete': 'destroy'})),
        path('authors/', views.AuthorView.as_view(actions={'post': 'create', 'get': 'list'})),
    
        # 3 作者详情增删改查
        re_path('^authordetails/(?P<pk>d+)',
                views.AuthorDetailView.as_view(actions={'get': 'retrieve', 'put': 'update', 'delete': 'destroy'})),
        path('authordetails/', views.AuthorDetailView.as_view(actions={'post': 'create', 'get': 'list'})),
    
        # 4 出版社表增删改查
        re_path('^publishs/(?P<pk>d+)',
                views.PublishView.as_view(actions={'get': 'retrieve', 'put': 'update', 'delete': 'destroy'})),
        path('publishs/', views.PublishView.as_view(actions={'post': 'create', 'get': 'list'})),
    ]
    
    

    2.2 模型表models.py

    class Book(models.Model):
        title = models.CharField(max_length=32)
        price = models.DecimalField(max_digits=8, decimal_places=2)
        authors = models.ManyToManyField(to='Author')
        publish = models.ForeignKey(to='Publish', on_delete=models.CASCADE, null=True)
    
    
    class Author(models.Model):
        name = models.CharField(max_length=16)
        age = models.IntegerField()
        detail = models.OneToOneField(to='AuthorDetail', on_delete=models.CASCADE)
    
    
    class AuthorDetail(models.Model):
        phone = models.CharField(max_length=12)
        addr = models.CharField(max_length=32)
    
    
    class Publish(models.Model):
        pub_name = models.CharField(max_length=32)
        email = models.EmailField()
    
    

    2.3 视图views.py

    image-20200712214126109

    from rest_framework.response import Response
    from app01.models import Book, Publish,Author,AuthorDetail
    from rest_framework.viewsets import ModelViewSet, ReadOnlyModelViewSet
    from app01.ser import get_serializer_1
    
    
    # Create your views here.
    
    
    # 自定义响应
    class MyResponse():
        def __init__(self):
            self.status = 100
            self.msg = '成功'
    
        @property
        def get_dict(self):
            return self.__dict__
    
    
    response = MyResponse()
    
    
    # 1 图书视图
    class BookView(ModelViewSet):
        queryset = Book.objects
    
        def get_serializer_class(self):
            return get_serializer_1('book')
    
        def delete(self, request, pk=None):
            response = MyResponse()
            if not pk:
                book_query = Book.objects.all()
                for book in book_query:
                    book.authors.remove()
                book_query.delete()
                response.msg = '所有数据已删除'
                return Response(response.get_dict)
            else:
                book = Book.objects.filter(pk=pk)
                if not book:
                    response.status = 101
                    response.msg = f'不存在主键值为{pk}的书籍,无法删除 '
                    return Response(response.get_dict)
                book.authors.remove()
                book.delete()
                response.msg = f'主键值为{pk}的书籍,已删除 '
                return Response(response.get_dict)
    
    
    # 2 作者视图
    class AuthorView(ModelViewSet):
        queryset = Author.objects
    
        def get_serializer_class(self):
            return get_serializer_1('author')
    
        def delete(self, request, pk=None):
            if not pk:
                author_query = Author.objects.all()
                for author in author_query:
                    author.book_set.all().delete()
                author_query.delete()
                response.msg = '所有数据已删除'
                return Response(response.get_dict)
            else:
                author = Author.objects.filter(pk=pk)
                if not author:
                    response.status = 101
                    response.msg = f'不存在主键值为{pk}的作者,无法删除 '
                    return Response(response.get_dict)
                author.book_set.all().delete()
                author.delete()
                response.msg = f'主键值为{pk}的作者,已删除 '
                return Response(response.get_dict)
    
    
    # 3 作者详情视图
    class AuthorDetailView(ModelViewSet):
        queryset = AuthorDetail.objects
    
        def get_serializer_class(self):
            return get_serializer_1('authordetail')
    
        def delete(self, request, pk=None):
            if not pk:
                author_detail_query = AuthorDetail.objects.all()
                for detail in author_detail_query:
                    detail.author.delete()
                author_detail_query.delete()
                response.msg = '所有数据已删除'
                return Response(response.get_dict)
            else:
                detail = AuthorDetail.objects.filter(pk=pk)
                if not detail:
                    response.status = 101
                    response.msg = f'不存在主键值为{pk}的作者详情,无法删除 '
                    return Response(response.get_dict)
                detail.author.delete()
                detail.delete()
                response.msg = f'主键值为{pk}的作者详情,已删除 '
                return Response(response.get_dict)
    
    
    # 3 出版社视图
    class PublishView(ModelViewSet):
        queryset = Publish.objects
    
        def get_serializer_class(self):
            return get_serializer_1('publish')
    
        def delete(self, request, pk=None):
            if not pk:
                publish_query = Publish.objects.all()
                for publish in publish_query:
                    publish.book_set.all().delete()
                publish_query.delete()
                response.msg = '所有数据已删除'
                return Response(response.get_dict)
            else:
                publish = Publish.objects.filter(pk=pk)
                if not publish:
                    response.status = 101
                    response.msg = f'不存在主键值为{pk}的出版社,无法删除 '
                    return Response(response.get_dict)
                publish.book_set.all().delete()
                publish.delete()
                response.msg = f'主键值为{pk}的出版社,已删除 '
                return Response(response.get_dict)
    

    2.4 序列化 器文件ser.py

    image-20200712221906294

    from rest_framework import serializers
    from app01.models import Book, Publish, AuthorDetail, Author
    from rest_framework.exceptions import ValidationError
    
    
    # 1.书籍序列化类
    class BookSerializer(serializers.Serializer):
        id = serializers.IntegerField(read_only=True)
        title = serializers.CharField(max_length=32, min_length=2)
        price = serializers.DecimalField(max_digits=8, decimal_places=2)
        publish = serializers.CharField(source='publish.pub_name', read_only=True)
        authors = serializers.SerializerMethodField(read_only=True)
        authors_id = serializers.ListField(write_only=True)
        publish_id = serializers.IntegerField(write_only=True)
    
        def get_authors(self, instance):
            authors = instance.authors.all()
            l1 = []
            for author in authors:
                l1.append({'name': author.name, 'age': author.age})
            return l1
    
        def create(self, validated_data):
            title = validated_data.get('title')
            price = validated_data.get('price')
            publish_id = validated_data.get('publish_id')
            authors_id = validated_data.get('authors_id')
            instance = Book.objects.create(title=title,
                                           price=price,
                                           publish_id=publish_id)
            authors_id_list = [int(x) for x in authors_id]
            for i in authors_id_list:
                instance.authors.add(i)
            return instance
    
        def update(self, instance, validated_data):
            instance.title = validated_data.get('title')
            instance.price = validated_data.get('price')
            instance.publish_id = validated_data.get('publish_id')
            authors_id_list = validated_data.get('authors_id')
            authors_id_list = [int(x) for x in authors_id_list]
            instance.authors.set(authors_id_list)
            instance.save()
            return instance
    
        def validate_authors_id(self, data):
            exist_author = list(Author.objects.all().values('id'))
            exist_author = [x.get('id') for x in exist_author]
            if len(data) == 1:
                data_1 = data
            else:
                data_1 = sorted(data)
            print(f'存在的作者id:{exist_author}')
            print(f'上传的作者id:{data_1}')
            if not set(data_1) <= set(exist_author):
                raise ValidationError('上传的主键没有对应的作者')
            return data
    
        def validate_publish_id(self, data):
            exist_publish = Publish.objects.all().values('id')
            exist_publish = [x.get('id') for x in exist_publish]
            print(f'存在的出版社id:{exist_publish}')
            print(f'上传的出版社id:{data}')
            if data not in exist_publish:
                raise ValidationError('上传的主键没有对应的出版社')
            return data
    
    
    # 2.作者序列化类
    class AuthorSerializer(serializers.Serializer):
        id = serializers.IntegerField(read_only=True)
        name = serializers.CharField(max_length=16, min_length=2)
        age = serializers.IntegerField()
        detail = serializers.SerializerMethodField(read_only=True)
        detail_id = serializers.IntegerField(write_only=True)
    
        def get_detail(self, instance):
            print(instance)
            return {'电话': instance.detail.phone, '居住城市': instance.detail.addr}
    
        def create(self, validated_data):
            name = validated_data.get('name')
            age = validated_data.get('age')
            detail_id = validated_data.get('detail_id')
            instance = Author.objects.create(name=name,
                                             age=age,
                                             detail_id=detail_id)
            return instance
    
        def update(self, instance, validated_data):
            instance.name = validated_data.get('name')
            instance.age = validated_data.get('age')
            instance.detail_id = validated_data.get('detail_id')
            instance.save()
            return instance
    
        def validate_detail_id(self, data):
            detail = AuthorDetail.objects.filter(pk=data)
            if not detail:
                raise ValidationError(f'上传的详情id【{data}】没有对应的详情')
            else:
                author = Author.objects.filter(detail=data).first()
                if author:
                    raise ValidationError(f'上传的详情id【{data}】已存在作者【{author.name}】,请绑定别的作者详情')
            return data
    
        def validate_name(self, data):
            author = Author.objects.filter(name=data)
            if author:
                raise ValidationError(f'作者【{data}】已存在')
            return data
    
    
    # 3.作者详情序列化类
    class AuthorDetailSerializer(serializers.ModelSerializer):
        class Meta:
            model = AuthorDetail
            fields = '__all__'
    
    
    # 4.出版社序列化类
    class PublishSerializer(serializers.ModelSerializer):
        class Meta:
            model = Publish
            fields = '__all__'
    
    
    #  根据不同的视图获取不同的序列化类方法
    def get_serializer_1(query_class):
        if query_class == 'book':
            return BookSerializer
        elif query_class == 'author':
            return AuthorSerializer
        elif query_class == 'publish':
            return PublishSerializer
        else:
            return AuthorDetailSerializer
    
    

    2.5 数据:

    作者详情:

    image-20200713004227227

    作者:

    image-20200712223857651

    出版社:

    image-20200712223930804

    图书:

    image-20200712224015353

    图书与作者对应关系:

    image-20200712224100851

    2.6 测试效果:

    2.6.1 图书增删改查:

    获取所有图书:

    image-20200712224643280

    获取指定主键的图书:

    image-20200712224751359

    修改指定主键的图书:

    image-20200712225433618

    新增书籍:

    image-20200713002737758

    删除指定主键的书籍:

    image-20200713002924052

    再次获取刚刚删除的书籍,已不存在:

    image-20200713003318666

    2.6.2 作者增删改查

    获取所有作者:

    image-20200713003823711

    获取单个作者:

    image-20200713003917516

    修改

    image-20200713004326713

    删除:

    image-20200713004509241

    再次获取刚刚删除的作者,已不存在

    image-20200713004620892

    新增:

    image-20200713004741331

    2.6.3 作者详情增删改查

    获取所有作者详情:

    image-20200713005051652

    获取单个作者详情:

    image-20200713005226751

    修改:

    image-20200713005547203

    删除:

    image-20200713005709699

    再次获取刚刚删除的作者详情以不存在:

    image-20200713005913544

    新增:

    image-20200713005805048

    2.6.4 出版社增删改查

    获取所有出版社:

    image-20200713010205723

    获取单个

    image-20200713010356812

    修改:

    image-20200713010624141

    删除:

    image-20200713010839673

    再次获取刚刚删除的出版社,已不存在:

    image-20200713010925601

    新增:

    image-20200713011055664

    3 过滤,排序,认证,权限,频率,异常处理

    # urls.py
    from app01 import views
    urlpatterns = [
        path(r'login/', views.LoginView.as_view()),
        path(r'test1/', views.TestView.as_view()),
        path(r'test3/', views.TestView3.as_view()),
        path(r'test4/', views.TestView4.as_view()),
        path(r'test5/', views.TestView5.as_view()),
        path(r'test6/', views.Book2View.as_view()),
    ]
    
    
    
    
    
    
    # views.py
    from django.shortcuts import render
    from app01 import app_auth
    from rest_framework.views import APIView
    from rest_framework.response import Response
    import uuid
    from app01 import models
    from rest_framework.permissions import IsAdminUser
    from rest_framework.authentication import SessionAuthentication
    from app01.app_auth import MyAuthentication
    from app01.app_auth import UserPermission
    
    
    # Create your views here.
    
    
    class LoginView(APIView):
        authentication_classes = []
        permission_classes = []
    
        def post(self, request):
            print(1)
            username = request.data.get('username')
            password = request.data.get('password')
            user = models.User.objects.filter(username=username, password=password)
            if user:
                user = user.first()
                token = uuid.uuid4()
                models.UserToken.objects.update_or_create(defaults={'token': token}, user=user)
                return Response({'status': 100, 'msg': '登陆成功', 'token': token})
            else:
                return Response({'status': 101, 'msg': '用户名或密码错误'})
    
    
    class TestView(APIView):
        authentication_classes = [app_auth.MyAuthentication]
        permission_classes = [app_auth.UserPermission]
    
        def get(self, request, *args, **kwargs):
            print('只有超级用户可以查看')
            print('我是测试数据')
            return Response('测试')
    
    
    # 2 内置权限,超级管理员可以查看
    
    
    class TestView3(APIView):
        authentication_classes = [SessionAuthentication]
        permission_classes = [IsAdminUser]
    
        def get(self, request):
            return Response('2222,只有草鸡用户能够观看')
    
    
    # 解析组件
    from rest_framework.parsers import MultiPartParser
    
    ## 频率限制
    from rest_framework.throttling import BaseThrottle, AnonRateThrottle, UserRateThrottle
    
    
    # 3 全局未登录用户访问频率校验
    class TestView4(APIView):
        authentication_classes = [MyAuthentication]
        permission_classes = [UserPermission]
        throttle_classes = [AnonRateThrottle]
    
        def get(self, request):
            return Response('我是未登录的用户')
    
    
    # 4 登陆用户每分钟访问10次,未登录用户访问五次
    class TestView5(APIView):
        # authentication_classes = [MyAuthentication]
        # permission_classes = [UserPermission]
        authentication_classes = [SessionAuthentication]
        throttle_classes = [AnonRateThrottle, UserRateThrottle]
    
        def get(self, request):
            a = request.user
            # if isinstance(a,)
            from django.contrib.auth.models import AnonymousUser
            print(a, type(a))
            if not isinstance(a, AnonymousUser):
                return Response('我是登录的用户')
            else:
                return Response('我是未登陆的用户')
    
    
    # 排序组件的使用
    from rest_framework.generics import ListAPIView
    from rest_framework.filters import OrderingFilter
    from app01.models import Book
    from app01.ser import BookSerializer
    
    
    class Book2View(ListAPIView):
        queryset = Book.objects.all()
        serializer_class = BookSerializer
        filter_backends = [OrderingFilter]
        ordering_fields = ('id', 'price')
    
    
    
    
    
    
    
    
    
    # app_auth.py
    from rest_framework import status
    from rest_framework.authentication import BaseAuthentication
    from rest_framework.exceptions import AuthenticationFailed
    from app01.models import UserToken
    from rest_framework.permissions import BasePermission
    from rest_framework.response import Response
    
    
    class MyAuthentication(BaseAuthentication):
        def authenticate(self, request):
            token = request.GET.get('token')
            print(token)
            if token:
                user_token = UserToken.objects.filter(token=token).first()
                print(user_token)
                if user_token:
                    return user_token.user, token
                else:
                    raise AuthenticationFailed('认证失败')
    
            else:
                raise AuthenticationFailed('请求中必须有token')
    
    
    class UserPermission(BasePermission):
        def has_permission(self, request, view):
            user = request.user
            if user.user_type == 1:
                return True
            else:
                return False
    
    
    from rest_framework.views import exception_handler
    
    
    def my_exception_handle(exc, context):
        response = exception_handler(exc, context)
        # 两种情况,一个是None,drf没有处理
        # response对象,django处理了,但是处理的不符合要求
        print(type(exc))
    
        if not response:
            if isinstance(exc, ZeroDivisionError):
                return Response(data={'status': 777, 'msg': '除以0的错误' + str(exc)}, status=status.HTTP_400_BAD_REQUEST)
            return Response(data={'status': 999, 'msg': str(exc)})
        else:
            pass
    
    
    # 全局异常处理
    from rest_framework.views import exception_handler
    from rest_framework.response import Response
    from rest_framework import status
    
    
    def my_exception_handler(exc, context):
        response = exception_handler(exc, context)
        # 两种情况,一个是None,drf没有处理
        # response对象,django处理了,但是处理的不符合咱们的要求
        # print(type(exc))
    
        if not response:
            if isinstance(exc, ZeroDivisionError):
                return Response(data={'status': 777, 'msg': "除以0的错误" + str(exc)}, status=status.HTTP_400_BAD_REQUEST)
            return Response(data={'status': 999, 'msg': str(exc)}, status=status.HTTP_400_BAD_REQUEST)
        else:
            # return response
            return Response(data={'status': 888, 'msg': response.data.get('detail')}, status=status.HTTP_400_BAD_REQUEST)
    
    # 全局配置setting.py
    """
    'EXCEPTION_HANDLER': 'app01.app_auth.my_exception_handler'"""
    
    
    
    
    
    
    # ser.py
    from rest_framework import serializers
    from app01.models import Book
    
    
    class BookSerializer(serializers.ModelSerializer):
        class Meta:
            model = Book
            fields = '__all__'
    
    
  • 相关阅读:
    PAT B1045 快速排序 (25 分)
    PAT B1042 字符统计 (20 分)
    PAT B1040 有几个PAT (25 分)
    PAT B1035 插入与归并 (25 分)
    PAT B1034 有理数四则运算 (20 分)
    PAT B1033 旧键盘打字 (20 分)
    HDU 1231 最大连续子序列
    HDU 1166 敌兵布阵
    HDU 1715 大菲波数
    HDU 1016 Prime Ring Problem
  • 原文地址:https://www.cnblogs.com/zhangtieshan/p/13291282.html
Copyright © 2011-2022 走看看