python drf各类组件的用法和作用
程序员文章站
2022-03-13 21:22:01
drf组件的用法和作用认证自定义认证的类 """ from rest_framework.authentication import baseauthentication from res...
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<format>[a-z0-9]+)/?$ [name='bookpage-list'] ^api/ v1/ ^bookpage/(?p<pk>[^/.]+)/$ [name='bookpage-detail'] ^api/ v1/ ^bookpage/(?p<pk>[^/.]+)\.(?p<format>[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<version>[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组件的资料请关注其它相关文章!