django resetful framework

  • Django rest framework(1)----认证
  • Django rest framework(2)----权限
  • Django rest framework(3)----节流
  • Django rest framework(4)----版本
  • Django rest framework(5)----解析器
  • Django rest framework(6)----序列化
  • Django rest framework(7)----分页

 

序列化

对queryset 序列化一般  继承两个类  serializers.Seriailzer  和 serializers.ModelSerializer 

models.py

from django.db import models

# Create your models here.

class Article(models.Model):
    title = models.CharField(max_length=32,unique=True, null=False)
    desc = models.TextField()
    create_time = models.DateTimeField(auto_now_add=True)
    is_show = models.BooleanField(default=1)
    author=models.ForeignKey(to='UserInfo',on_delete=models.CASCADE,default=1)

    class Meta:
        db_table = 'article'



class UserInfo(models.Model):
    USER_TYPE = (
        (1,'普通用户'),
        (2,'VIP'),
        (3,'SVIP')
    )

    user_type = models.IntegerField(choices=USER_TYPE)
    username = models.CharField(max_length=32)
    password = models.CharField(max_length=64)

class UserToken(models.Model):
    user = models.OneToOneField(UserInfo,on_delete=models.CASCADE)
    token = models.CharField(max_length=64)

 

serializers.py

# 一 *****序列化相关
# Serializer 序列化的字段需要自己定义
# ModelSerializer 可以在 Meta里面fields = ‘__all__’ 序列化所有 
# 序列化都是不能 对外键关系进行更深层次的序列化 
# 如果需要序列化外键所关联对象 需要在继承 ModelSelrialzer 中 添加 depth=1
  class Meta:
    fields='__all__'
    model = 'xxxxx'
    depth = 1 将会学序列化外键数据 如果是 2 将会序列化外键的外键数据
# 所以我们需要有时需要返回 一种所需要的数据结构就需要重构
# 1 在类中显示的声明你需要序列化的字段名称 再用 def get_名称(self,obj) -->obj为每当前对象
# 2 重写 to_representation方法 在super().to_representation 中找到你需要修改的参数进行修改
# 以上两种方法都需要返回一个 序列化之后的数据
# 二 ******数据校验相关
# 在继承序列化类中可进行 数据验证类似于 Django的Form组件

from rest_framework import serializers

from app1.models import Article, UserInfo

class UserSerializer(serializers.Serializer):
    #username=serializers.CharField(source='username') 错误写法 不能重复指定
    username=serializers.CharField() 
    password=serializers.CharField()
    user_type=serializers.CharField()
    article=serializers.SerializerMethodField()
    # 修改了article返回的数据 如不修改默认返回 数据库原有的数据  就是int类型的数据 
    # 第一种 重构数据 的方法
    def get_article(self,obj):
        res=obj.article_set.all()
        serializer=ArticleSerializer(instance=res,many=True)
        return serializer.data


class User2Serializer(serializers.ModelSerializer):
    class Meta:
        model = UserInfo
        fields='__all__'

class ArticleSerializer(serializers.ModelSerializer):

    # author=serializers.SerializerMethodField()
    class Meta:
        model = Article
        fields="__all__"

    # def get_author(self,obj):
    #     # data=UserSerializer(instance=obj.author,many=False).data # 一开始这样写发现报栈              
   #  溢出后来返现原来是写了个死循环 --相互序列化 低级错误
    #     res=User2Serializer(obj.author).data
    #     return res
    # 第二种 重构返回数据的  方法  instance 就是当前被序列化的对象
    def to_representation(self, instance):
        data=super().to_representation(instance)
        data['author']=User2Serializer(instance=instance.author,many=False).data

        return data

class UserTokenSerializer(serializers.Serializer):
    token=serializers.CharField()
    username=serializers.CharField(source='user.username') # 指定查询数据库中的字段

认证

一 、局部认证
    在当前类中添加
    class XXX(APIView):
        authentication_classes=[你写的认证类]
        pass
    
    认证类推荐继承 BasicAuthentication
    例子
    from rest_framework.authentication import BaseAuthentication
    from rest_framework import exception
    class UserAuth(BaseAuthentication):
        # 必须重写以下两个方法
        def authenticate(self,request):
            token=request.query_params.get('id')
            # 用户没通过认证 --一般抛异常
            if not token:
                raise exception.AuthenticationFailed({'code':900,'msg':‘认证失败’})
            # 认证通过 需返回两个值 一个是user 一个是token
            user_obj=通过查数据库得到
            return user_obj,token  ----其实是  request.user=user_obj (全局)  
        def authenticate_header(self, request):
            pass
    

二 、全局认证
settings中配置

REST_FRAMEWORK={
    'DEFAULT_AUTHENTICATION_CLASSES':(你写的认证类路径 不能写在views中,) --这可以为一个元祖或可迭代对象
}

权限

和认证差不多,但是使用权限的前提必须要使用认证 这个想想就知道了 ("Authentication credentials were not provided.")

一、局部权限认证
    class XXX(APIView):
        permission_classes
    
    推荐继承 BasicPermission
    from rest_framework.permissions import BasePermission
    from rest_framework import exceptions
            exceptions.PermissionDenied 
    class UserPermission(BasePermission):
          # 看一下源码就知道要重写什么方法
          def has_permission(self,request,view):
                权限处理逻辑
                 
                return True #认证通过
                return False # 没过
            
        
        



二、全局权限认证

在settings中配置

REST_FRAMEWORK={
    'DEFAULT_PERMISSION_CLASSES':(你写的权限类路径 不能写在views中,) --这可以为一个元祖或可迭代对象
}

节流

第一种写法  继承BaseThrottle

from rest_framework.throttling import BaseThrottle

vist_data = {}

# 定义一个类 (你要写限制的类)
class VisitThrottle(BaseThrottle):
    '''匿名用户60s只能访问三次(根据ip)''
    history = None
    def allow_request(self, request, view):

        cur_time = time.time()
        identify = self.get_ident(request)
        if identify not in vist_data:
            vist_data[identify] = []
            vist_data[identify].append(cur_time)
            return True
        res = vist_data[identify]
        self.history = res
        if res:
            if res[-1] + 60 > cur_time:
                if len(res) < 3:
                    res.insert(0, cur_time)
                    return True
                return False
            else:
                res.pop()
                return True
        else:
            res.append(cur_time)
            return True

    # 超过访问次数之后的 可访问剩余时间
    def wait(self):
        
        return 60 - (time.time() - self.history[-1])

第二种继承SimpleRateThrottle

class VisitThrottle(SimpleRateThrottle):
#
#      # 什么都不需要重写 只需要定义一个 scope 和 get_cache_key 返回当前身份 
    
      scope = 'NBA' # 继承BaseThrottle 是不需要scope
#
#    
#     def get_cache_key(self, request, view):
#         # 通过ip限制节流
#         return self.get_ident(request)


settgins.py

'DEFAULT_THROTTLE_CLASSES': ('utils.throttle.VisitThrottle',),
# 继承SimpleRateThrottle 必须做以下配置
"DEFAULT_THROTTLE_RATES":{
            'NBA':'5/m',         #没登录用户3/m,NBA就是scope定义的值
            'NBAUser':'3/m',    #登录用户10/m,NBAUser就是scope定义的值
            # NBA 和NBAUser  可以使不同的APIView 使用不同的节流方式
        }

 

分页 

第一种方式

class Pager1View(APIView):
    def get(self,request,*args,**kwargs):
        #获取所有数据
        roles = models.Role.objects.all()
        #创建分页对象
        pg = PageNumberPagination()
        #获取分页的数据
        page_roles = pg.paginate_queryset(queryset=roles,request=request,view=self)
        #对数据进行序列化
        ser = PagerSerialiser(instance=page_roles,many=True)
        return Response(ser.data)

settings.py 一定要配置分页 否则返回 [ ] 

REST_FRAMEWORK={
    "PAGE_SIZE":2  # 每页数量
}

 第二种方式 自定义分页类继承

#自定义分页类
class MyPageNumberPagination(PageNumberPagination):
    #每页显示多少个
    page_size = 3
    #默认每页显示3个,可以通过传入pager1/?page=2&size=4,改变默认每页显示的个数
    page_size_query_param = "size"
    #最大页数不超过10
    max_page_size = 10
    #获取页码数的
    page_query_param = "page"


class Pager1View(APIView):
    def get(self,request,*args,**kwargs):
        #获取所有数据
        roles = models.Role.objects.all()
        #创建分页对象,这里是自定义的MyPageNumberPagination
        pg = MyPageNumberPagination()
        #获取分页的数据
        page_roles = pg.paginate_queryset(queryset=roles,request=request,view=self)
        #对数据进行序列化
        ser = PagerSerialiser(instance=page_roles,many=True)
        return Response(ser.data)

 

原文链接 http://www.cnblogs.com/derek1184405959/p/8727595.html

 

 

 

 


 

你可能感兴趣的:(Django)