DRF组件的用法和作用

认证

自定义认证的类

"""

from rest_framework.authentication import BaseAuthentication

from rest_framework.exceptions import AuthenticationFailed

from authapp.models import UserToken

class MyOrderAuthentication(BaseAuthentication):

在这里实现认证的逻辑

def authenticate(self, request):

token = request._request.GET.get('token')

# 获取到token之后,需要在数据库中查找token

obj = UserToken.objects.filter(token=token).first()

if not obj:

# 没有通过认证

raise AuthenticationFailed('认证失败')

# 返回元组( user, auth )

return (obj.user, obj)

"""

使用局部配置(在视图函数中)

"""

class OrderView(APIView):

# 通过authentication_classes设置认证类

authentication_classes = [MyOrderAuthentication,]

# 通过authentication_classes设置为空列表,就不再进行认证了

# authentication_classes = []

"""

全局配置

"""

REST_FRAMEWORK = {

'DEFAULT_AUTHENTICATION_CLASSES':['unitls.authentication.MyOrderAuthentication'],

}

"""

设置匿名用户

"""

REST_FRAMEWORK = {

'UNAUTHENTICATED_USER': lambda :"匿名用户",

'UNAUTHENTICATED_TOKEN': lambda :'123456',

}

"""

## 最最重要的,理清认证的源代码

权限

自定义权限类

"""

from rest_framework.permissions import BasePermission

class MyOrderPermission(BasePermission):

#自定义权限认证的类,必须要实现has_permission方法

message = '你不是超级用户,没有权限访问'

def has_permission(self, request, view):

#Return `True` if permission is granted, `False` otherwise.

#返回True表示有权限访问,返回False表示没有权限访问

if request.user.user_type != 3:

return False

return True

"""

局部使用

"""

class OrderView(APIView):

# permission_classes设置权限类

permission_classes = [MyOrderPermission,]

# 通过authentication_classes设置为空列表,就不再进行权限认证了

permission_classes = []

"""

全局的设定

"""

REST_FRAMEWORK = {

'DEFAULT_PERMISSION_CLASSES':['unitls.permission.MyOrderPermission'],

}

"""

最最重要的,理清权限认证的源代码

分页

自定义分页类PageNumberPagination

# 自定制分页类

class MyPageNumberPagination(PageNumberPagination):

"""http://127.0.0.1:8000/api/userpage/?page=1&pagesize=10"""

# page_size每一返回多少条

page_size = 5

# 设置分页的参数名

page_query_param = 'page'

# 设置每页返回数据量的参数名

page_size_query_param = 'pagesize'

# 设置每页最大返回的条数

max_page_size = 6

使用

class UsersPageView(APIView):

def get(self,request,*args,**kwargs):

# 获取表中所有用户的row(记录)

obj = models.UserInfo.objects.all()

#实例化分页的类

#page_obj = PageNumberPagination()

page_obj = MyPageNumberPagination()

#获取分页数据

page_data = page_obj.paginate_queryset( queryset=obj,request=request,view=self)

# 序列化

ser = UsersSerializer(instance=page_data,many=True)

# return Response(ser.data)

#get_paginated_response会返回上一页下一页和总条数

return page_obj.get_paginated_response(ser.data)

自定义分页类LimitOffsetPagination

from rest_framework.pagination import LimitOffsetPagination

class MyLimitOffsetPagination(LimitOffsetPagination):

"""http://127.0.0.1:8000/api/userpage/?limit=10&offset=0"""

default_limit = 5

limit_query_param = 'limit'

offset_query_param = 'offset'

max_limit = 7

自定义分页类CursorPagination(会对分页参数进行加密)

from rest_framework.pagination import CursorPagination

class MyCursorPagination(CursorPagination):

"""http://127.0.0.1:8000/api/userpage/?cursor=cD01"""

cursor_query_param = 'cursor'

page_size = 4

#返回数据市的排序的方式

ordering = '-id'

max_page_size = 8

设置全局的分页

"""

REST_FRAMEWORK = {

'DEFAULT_PAGINATION_CLASS':'unitl.pagination.MyCursorPagination',

'PAGE_SIZE':3

}

"""

视图

以前 (Django的View)

"""

class MyView(View)

.....

"""

现在(rest_framework的APIView)

"""

class MyView(APIView)

.....

"""

其他视图的使用

第一个:GenericAPIView 视图的使用 (跟继承自APIViewq其实一样,只是我们在外面逻辑,

GenericAPIView在内部c定制方法帮我们实现了)

"""

from rest_framework.generics import GenericAPIView

class BookinfoSeralizer(serializers.ModelSerializer):

class Meta:

model = models.BookInfo

fields = "__all__"

class BookView(GenericAPIView):

# queryset: 设置获取的数据

queryset = models.BookInfo.objects.all()

# serializer_class: 设置序列化的类

serializer_class = BookinfoSeralizer

# pagination_class : 设置分页的类

pagination_class = MyPageNumberPagination

def get(self,request,*args,**kwargs):

obj = self.get_queryset() #=> obj = models.BookInfo.objects.all()

# 获取当前分页的数据

page_data = self.paginate_queryset(obj) #=>page_obj = MyPageNumberPagination() #获取分页数据page_data = page_obj.paginate_queryset()

# 获取序列化之后的数据

ser = self.get_serializer(instance=page_data,many=True) #->ser = BookinfoSeralizer(instance=page_data,many=True)

return Response(ser.data)

"""

第二个:GenericViewSet 视图的如下使用,注意路由会发生变化

"""

class BookView(GenericViewSet):

# queryset: 设置获取的数据

queryset = models.BookInfo.objects.all()

# serializer_class: 设置序列化的类

serializer_class = BookinfoSeralizer

# pagination_class : 设置分页的类

pagination_class = MyPageNumberPagination

def list(self,request,*args,**kwargs):

obj = self.get_queryset() #=> obj = models.BookInfo.objects.all()

# 获取当前分页的数据

page_data = self.paginate_queryset(obj) #=>page_obj = MyPageNumberPagination() #获取分页数据page_data = page_obj.paginate_queryset(

# 获取序列化之后的数据

ser = self.get_serializer(instance=page_data,many=True) #->ser = BookinfoSeralizer(instance=page_data,many=True)

return Response(ser.data)

"""

路由会发生变化,配置如下

"""

url(r"bookpage/$",views.BookView.as_view({'get': 'list'}),name='bookpage')

"""

第三个:ListModelMixin,CreateModelMixin,RetrieveModelMixin,

DestroyModelMixin,UpdateModelMixin 等视图的使用

"""

from rest_framework.mixins import ListModelMixin,CreateModelMixin,RetrieveModelMixin,DestroyModelMixin,UpdateModelMixin

from rest_framework.viewsets import GenericViewSet

# ListModelMixin : 返回列表数据据( get请求)

# CreateModelMixin : 新增一条数据 (Post请求)

# RetrieveModelMixin, : 获取详情数据 (get请求)

# DestroyModelMixin, : 删除数据的时候 (delete)

# UpdateModelMixin : 跟新数据的时候使用 (put)

class BookView(ListModelMixin,RetrieveModelMixin,CreateModelMixin,DestroyModelMixin,UpdateModelMixin,GenericViewSet):

# queryset: 设置获取的数据

queryset = models.BookInfo.objects.all()

# serializer_class: 设置序列化的类

serializer_class = BookinfoSeralizer

# pagination_class : 设置分页的类

pagination_class = MyPageNumberPagination

"""

第四个:ModelViewSet视图的使用

ModelViewSet继承自istModelMixin,CreateModelMixin,

RetrieveModelMixin,DestroyModelMixin,UpdateModelMixin视图

如果要实现最基本的增删改查功能,就直接继承自ModelViewSet

"""

from rest_framework.viewsets import ModelViewSet

class BookView(ModelViewSet):

# queryset: 设置获取的数据

queryset = models.BookInfo.objects.all()

# serializer_class: 设置序列化的类

serializer_class = BookinfoSeralizer

# pagination_class : 设置分页的类

pagination_class = MyPageNumberPagination

"""

视图使用小总结

只想实现简单的增删改查

ModelViewSet

只想增

CreateModelMixin,GenericViewSet

只想增删改

CreateModelMixin,DestroyModelMixin,UpdateModelMixin,GenericViewSet

如果视图中的业务逻辑复杂,以上都不能满足的时候,直接使用

APIView

#自动路由配置

"""

from django.conf.urls import url,include

from api import views

from rest_framework import routers

router = routers.DefaultRouter()

router.register(r"bookpage",views.BookView,base_name='bookpage')

urlpatterns = [

url(r'v1/',include(router.urls)),

]

"""

自动路由会生成四个接口

^api/ v1/ ^bookpage/$ [name='bookpage-list']

^api/ v1/ ^bookpage\.(?P[a-z0-9]+)/?$ [name='bookpage-list']

^api/ v1/ ^bookpage/(?P[^/.]+)/$ [name='bookpage-detail']

^api/ v1/ ^bookpage/(?P[^/.]+)\.(?P[a-z0-9]+)/?$ [name='bookpage-detail']

频率限制节流

节流:

自定义节流类

"""

VISIT_RECORD = {}

class VisitThrottle(object):

def __init__(self):

self.history = None

def allow_request(self,request,view):

#实现节流的逻辑

#基于ip做节流

# #获取用户访问的IP地址

# ip_address = request._request.META.get('REMOTE_ADDR')

ctime = time.time()

# if ip_address not in VISIT_RECORD:

# #第一次访问的时候将访问的时间存储在字典中(ip地址为Key,访问的时间为value值)

# VISIT_RECORD[ip_address] = [ctime,]

#

# #第二次访问的时候取出访问的历史记录

# history = VISIT_RECORD[ip_address]

# 基于用户的节流

username = request.user.username

if username not in VISIT_RECORD:

VISIT_RECORD[username] = [ctime, ]

history = VISIT_RECORD[username]

self.history = history

while history and history[-1] < ctime - 10:

#如果访问的时间记录超过60秒,就把超过60秒的时间记录移除

history.pop()

if len(history) < 6:

history.insert(0,ctime)

return True

return False

def wait(self):

#一旦用户访问次数到达阀值,显示用户需要等待的时间

ctime = time.time()

#09:54:30 09:54:28

return 10 - (ctime - self.history[-1])

"""

局部使用

"""

class OrderView(APIView):

# throttle_classes设置节流类

throttle_classes = [VisitThrottle,]

"""

全局设置

"""

REST_FRAMEWORK = {

'DEFAULT_THROTTLE_CLASSES':['unitls.throttle.VisitThrottle'],

}

"""

使用DRF内置的限频类

"""

from rest_framework.throttling import SimpleRateThrottle

#推荐使用这种

class VisitThrottle(SimpleRateThrottle):

#没有登录用户,每分钟访问10次

scope = 'logined'

def get_cache_key(self, request, view):

return request.user.username

"""

全局设置

"""

REST_FRAMEWORK = {

'DEFAULT_THROTTLE_RATES':{

'unlogin':'10/m',

'logined':'3/m',

},

'DEFAULT_THROTTLE_CLASSES':['unitls.throttle.VisitThrottle'],

}

"""

版本控制

自定义版本控制类

"""

class ParmasVersion(object):

def determine_version(self, request, *args, **kwargs):

version = request.query_params.get('version')

return version

"""

使用(局部)

"""

class VersionView(APIView):

#设置获取版本的类

versioning_class = ParmasVersion

"""

全局设置

"""

'DEFAULT_VERSIONING_CLASS':'unitls.version.ParmasVersion',

"""

使用 DRF内置的版本控制类QueryParameterVersioning(局部)

"""

from rest_framework.versioning import QueryParameterVersioning

class VersionView(APIView):

#设置获取版本的类

versioning_class = QueryParameterVersioning

"""

设置文件中的配置信息

"""

REST_FRAMEWORK = {

'VERSION_PARAM':'version',

'DEFAULT_VERSION':'v1',

'ALLOWED_VERSIONS':['v1','v2'],

}

"""

全局设置

"""

REST_FRAMEWORK = {

'VERSION_PARAM':'version',

'DEFAULT_VERSION':'v1',

'ALLOWED_VERSIONS':['v1','v2'],

'DEFAULT_VERSIONING_CLASS':'rest_framework.versioning.QueryParameterVersioning',

}

"""

使用 DRF内置的版本控制类URLPathVersioning(局部)

"""

from rest_framework.versioning import URLPathVersioning

class VersionView(APIView):

#设置获取版本的类

versioning_class = URLPathVersioning

"""

设置文件中的配置信息

"""

REST_FRAMEWORK = {

'VERSION_PARAM':'version',

'DEFAULT_VERSION':'v1',

'ALLOWED_VERSIONS':['v1','v2'],

}

"""

全局设置

"""

REST_FRAMEWORK = {

'VERSION_PARAM':'version',

'DEFAULT_VERSION':'v1',

'ALLOWED_VERSIONS':['v1','v2'],

'DEFAULT_VERSIONING_CLASS':'rest_framework.versioning.URLPathVersioning',

}

"""

如果使用URLPathVersioning,路由格式如下

"""

url(r"^(?P[v1|v2]+)/version/",VersionView.as_view(),name='vvvv')

"""

#使用 DRF内置的版本控制类URLPathVersioning 反向生成url地址

"""

#反向生成url地址 reverse

obj = request.versioning_scheme

url1 = obj.reverse(viewname='orders',request=request)

#使用django的reverse方法反响生成url地址

from django.urls import reverse

url2 = reverse(viewname='orders',kwargs={'version':'v2'})

"""

解析器

因为开发人员post请求上传数据时,传递的数据类型不同,我们可能在request._request.POST中获取不到数据

case1: Content-Type : application/x-www-form-urlencoded

服务端接收到的post请求的数据格式:username=xxxxx&age=18&sex=男

我们就可以在request._request.POST中获取到数据

"""

class UserInfoView(APIView):

def post(self,request,*args,**kwargs):

username = request._request.POST.get('username')

age = request._request.POST.get('age')

sex = request._request.POST.get('sex')

"""

case2:Content-Type:application/json

服务端接收到的post请求的数据格式就是json数据:{"username":"xxxx","age":"18","sex":"男"}

在request._request.POST中就获取不到数据,但是在request.body中可以拿到

"""

class UserInfoView(APIView):

def post(self,request,*args,**kwargs):

import json

data = json.loads(request.body.decode('utf8'))

print(data)

"""

DRF内置的解析器FormParser,JSONParser

使用(局部):

"""

from rest_framework.parsers import FormParser,JSONParser

class UserInfoView(APIView):

parser_classes = [FormParser,JSONParser]

#这时DRF 内部代码会根据request.Content-Type和解析器支持的media_type比较

从而选择对应的解析器

def post(self,request,*args,**kwargs):

# 如果使用JSONParser、FormParser解析数据的话

data = request.data

print(data)

"""

渲染器

渲染器

INSTALLED_APPS = [

'rest_framework',

]

from rest_framework.renderers import BrowsableAPIRenderer,JSONRenderer,AdminRenderer

class BookView(ModelViewSet):

# 设置渲染器类型

renderer_classes = [JSONRenderer]

序列化

Django的序列化

"""

#django序例化方式一

books = models.BookInfo.objects.all().values('id','bookname')

books = list(books)

print(type(books), books)

self.ret['books'] = books

#django序例化方式二

books = models.BookInfo.objects.all()

books = [model_to_dict(item) for item in books]

self.ret['books'] = books

"""

DRF 序列化

第一种:继承自serializers.Serializer

"""

class BookDetailSerializer(serializers.Serializer):

# 正常的字段序列化

id = serializers.IntegerField()

bookname = serializers.CharField()

author = serializers.CharField()

category = serializers.IntegerField()

bookdesc = serializers.CharField()

# 获取枚举类型的文本是 source=get_字段名_display

status = serializers.CharField(

source='get_status_display'

)

categoryname = serializers.CharField(

source='get_category_display'

)

# 自定义方法获取字段

chpaters = serializers.SerializerMethodField()

#序列化时可以自定义方法获取字段

def get_chpaters(self,row):

""" row - > bookinfo """

chpaters = models.ChpaterInfo.objects.filter(book=row)

ser = ChpaterSerializer(instance=chpaters,many=True,

context=self.context

)

return ser.data

"""

序列化时生成url

"""

url = serializers.HyperlinkedIdentityField(

view_name='chpaterdetail', lookup_field='id',

lookup_url_kwarg='pk',

)

"""

注意:如果序列化类中使用HyperlinkedIdentityField生成url,那我们在序例化时添加context={'request': request}

"""

ser = BookDetailSerializer(

instance=obj,many=False,

context={'request': request}

)

"""

如果出现关联关系时,获取model对像的某一个字段

"""

bookname = serializers.CharField(source='book.bookname')

"""

第二种继承自:serializers.ModelSerializer

"""

class ChpaterDetailSerializer(serializers.ModelSerializer):

#使用ModelSerializer进行章节详情的序列化

bookname = serializers.CharField(source='book.bookname')

class Meta:

model = models.ChpaterInfo

#fields = "__all__"

fields = ['id','bookname']

"""

DRF (序列化时)自定义方法获取数据

"""

book = serializers.SerializerMethodField()

"""

"""

def get_book(self,row):

""" row - > UserInfo"""

print('======',row.book.all())

ser = UsersBooksSerializer(

instance=row.book.all(),

many=True

)

return ser.data

"""

DRF depth深度的使用

# depth会根据关联的数据不停的深入将数据获取出来(最多不超过10层)

# depth = 1

"""

class UsersSerializer(serializers.ModelSerializer):

class Meta:

model = models.UserInfo

fields = "__all__"

#depth会根据关联的数据不停的深入将数据获取出来(最多不超过10层)

depth = 1

"""

DRF序列化的验证功能

"""

class UsersSerializer(serializers.ModelSerializer):

#自定义验证错误的信息

username = serializers.CharField(error_messages={'required':'用户名不能为空'})

class Meta:

model = models.UserInfo

fields = "__all__"

"""

"""

class UsersView(APIView):

def post(self,request,*args,**kwargs):

"""DRF 序列化自带验证功能"""

data = request.data

#print(data)

ser = UsersSerializer(data=data)

if ser.is_valid(): # ser.is_valid()y验证数据的有效性

print('验证后的数据',ser.validated_data)

#验证后的数据正确后,保存数据至数据库

ser.save()

else:

#上传数据不符合规范时ser.errors,返回错误详细

print(ser.errors)

return Response(data)

"""

自定义字段验证规则

"""

class UsersInfoSerializer(serializers.ModelSerializer):

username = serializers.CharField(error_messages={'required':'用户名不能为空'})

class Meta:

model = models.UserInfo

fields = "__all__"

# 用户名中必须包含老王两个字,不包含则认为名字无效

def validate_username(self,validated_value):

print(validated_value)

from rest_framework.exceptions import ValidationError

if '老王' not in validated_value:

#验证不通过,抛出异常

raise ValidationError('用户名不合法')

#验证通过,返回数据

return validated_value

"""

以上就是python drf各类组件的用法和作用的详细内容,更多关于python drf组件的资料请关注脚本之家其它相关文章!

python drf_python drf各类组件的用法和作用相关推荐

  1. python drf_python DRF操作流程

    # 其实就是Django RESTful Framework # RESTful一种API的命名风格,主要因为前后端分离开发出现 # 前后端分离: 用户访问静态文件的服务器,数据全部由ajax请求给到 ...

  2. python drf_python | DRF 框架知识总览

    DRF 框架 DRF 框架知识总览 接口(api) 什么是接口 定义 前台与后台进行信息交互的媒介 -- url链接 接口组成 url链接 - http://127.0.0.1:9000/api/us ...

  3. drf 频率组件 META字典详情

    drf频率组件 什么是频率 控制用户对某个url的请求频率,比如一分钟之内,只能访问三次 自定义频率规则 1.取出访问者ip 2.判断当前ip在不在访问字典中:不在,则添加进去,返回True; 3.循 ...

  4. Rest-framework之drf认证组件,权限组件+不存数据库的token认证

    Rest-framework之drf认证组件,权限组件 django中一个请求时一个reques,如果在哪个位置改了request,那么到了后面就是修改过的request 昨日回顾: 认证: -写一个 ...

  5. python基础_格式化输出(%用法和format用法)(转载)

    python基础_格式化输出(%用法和format用法) 目录 %用法 format用法 %用法 1.整数的输出 %o -- oct 八进制 %d -- dec 十进制 %x -- hex 十六进制 ...

  6. java ee各类组件_在Java EE组件中使用骆驼路线

    java ee各类组件 从现在开始我一直在与Camel合作,我真的很喜欢它的简单性. 在Java EE之上使用它一直是一个挑战,我最近发表了一篇关于如何做到这一点的演讲,而在Java EE中引导Cam ...

  7. python except用法和作用_Python面试题(部分附带面试标准答案) 建议收藏

    1.请尽可能列举python列表的成员方法,并给出一下列表操作的答案: (1) a=[1, 2, 3, 4, 5], a[::2]=?, a[-2:] = ? (2) 一行代码实现对列表a中的偶数位置 ...

  8. python中scrapy是什么_python爬虫中scrapy组件有哪些?作用是什么?

    最近苹果12的消息一直活跃,连小编这种不是果粉的人都知道了.虽然苹果是一部性能不错的手机,但是它各个零件却是来源于不同的地方,可见再好的成品也是需要不同零件支撑的.那么,python爬虫中scrapy ...

  9. [转载] python 字符串查找的4个方法和count函数

    参考链接: Python字符串 count 方法 python 字符串查找的4个方法和count函数 所谓的字符串查找方法就是查找子串在字符串中的位置和出现的次数 python 字符串查找有4个方法, ...

最新文章

  1. PDO(PHP Data Object),Mysqli,以及对sql注入等问题的解决
  2. .net 匹配html图片url_后端程序员不得不会的 Nginx 转发匹配规则
  3. 单片机机器周期怎么计算公式_单片机很好玩6,单片机是一切智能机器的基础,就是这么嚣张...
  4. Linux入门(6)——Ubuntu16.04安装atom
  5. 盘点618 .NET 程序员必“败”书单
  6. Linux中点号,星号,加号,问号实战
  7. ASP.NET数据绑定的记忆碎片
  8. 【仿59store校园o2o系统 v6.8】夜猫店+校园超市+学生街+微信公众号绑定+校园跑腿插件
  9. 11.4 final类
  10. 2017.3.11[bzoj2440][中山市选2011]完全平方数
  11. css 宋体_6.CSS字体属性
  12. ?php if ($modules) { ?,phpStudy安装鲶鱼CMS怎样开启伪静态
  13. Caused by: java.lang.NoSuchMethodException: init [class android.content.Context, interface andr解决
  14. 未来的计算机没有显示屏,不吹也不黑 解析未来显示的四种可能!
  15. Power query (Power BI)一步到位傻瓜式合并工作簿,史上最好用
  16. opencv normalize()函数详解
  17. C#如何遍历文件夹下的所有文件
  18. 计算机使用技巧爆文,自媒体原创(伪原创)爆文的写作技巧
  19. ESP32 的 I2C 原理 应用入门
  20. 软件工程案例教程答案(第三版)韩万江 姜立新 编著 课后题答案 (软件项目开发实践)

热门文章

  1. 手机忘记密码但是想保留数据怎样保留数据解开手机密码忘记锁屏密码保留数据不清除手机数据怎么解锁锁屏密码
  2. 在PowerPoint中将鼠标变成激光笔
  3. 局域网唤醒(WOL)与远程唤醒教程
  4. java处理图片的所有类_JAVA处理图片常用公共类
  5. vue中Table表格转为Excel文件的方法
  6. Oracle 12C -- 设置CDB启动后,PDBs自动启动
  7. 纤亿通生产高工专业解说——彩光模块灰光模块制造工艺及参数
  8. 新能源汽车远程监控车载终端TBOX
  9. 渗透测试-Linux常用命令知识积累
  10. Html5+开发之旅-从入门到放弃