标签:普通用户 get 获取 分页 outer war 角色 序列 click
1. 开发模式 - 普通开发方式(前后端放在一起写) - 前后端分离 2. 后端开发 为前端提供URL(API/接口的开发) 注:永远返回HttpResponse 3. Django FBV、CBV FBV,function base view def users(request): user_list = [‘alex‘,‘oldboy‘] return HttpResponse(json.dumps((user_list))) CBV,class base view 路由: url(r‘^students/‘, views.StudentsView.as_view()), 视图: from django.views import View class StudentsView(View): def get(self,request,*args,**kwargs): return HttpResponse(‘GET‘) def post(self, request, *args, **kwargs): return HttpResponse(‘POST‘) def put(self, request, *args, **kwargs): return HttpResponse(‘PUT‘) def delete(self, request, *args, **kwargs): return HttpResponse(‘DELETE‘) 4. 列表生成式 class Foo: pass class Bar: pass v = [] for i in [Foo,Bar]: obj = i() v.append(obj) v = [item() for item in [Foo,Bar]] v对象列表 5. 面向对象 - 封装 - 对同一类方法封装到类中 class File: 文件增删改查方法 Class DB: 数据库的方法 - 将数据封装到对象中 class File: def __init__(self,a1,a2): self.a1 = a1 self.xxx = a2 def get:... def delete:... def update:... def add:... obj1 = File(123,666) obj2 = File(456,999) PS: 扩展 class Request(object): def __init__(self,obj): self.obj = obj @property def user(self): return self.obj.authticate() class Auth(object): def __init__(self,name,age): self.name = name self.age = age def authticate(self): return self.name class APIView(object): def dispatch(self): self.f2() def f2(self): a = Auth(‘alex‘,18) b = Auth(‘oldboy‘,18) req = Request(b) print(req.user) obj = APIView() obj.dispatch() 1. restful 规范(建议) 2. django rest framework框架 内容详细: 0. FBV、CBV CBV,基于反射实现根据请求方式不同,执行不同的方法。 原理: url -> view方法 -> dispatch方法(反射执行其他:GET/POST/DELETE/PUT) 流程: class StudentsView(View): def dispatch(self, request, *args, **kwargs): print(‘before‘) ret = super(StudentsView,self).dispatch(request, *args, **kwargs) print(‘after‘) return ret def get(self,request,*args,**kwargs): return HttpResponse(‘GET‘) def post(self, request, *args, **kwargs): return HttpResponse(‘POST‘) def put(self, request, *args, **kwargs): return HttpResponse(‘PUT‘) def delete(self, request, *args, **kwargs): return HttpResponse(‘DELETE‘) 继承(多个类共用的功能,为了避免重复编写): from django.views import View class MyBaseView(object): def dispatch(self, request, *args, **kwargs): print(‘before‘) ret = super(MyBaseView,self).dispatch(request, *args, **kwargs) print(‘after‘) return ret class StudentsView(MyBaseView,View): def get(self,request,*args,**kwargs): print(‘get方法‘) return HttpResponse(‘GET‘) def post(self, request, *args, **kwargs): return HttpResponse(‘POST‘) def put(self, request, *args, **kwargs): return HttpResponse(‘PUT‘) def delete(self, request, *args, **kwargs): return HttpResponse(‘DELETE‘) ############################################################ class TeachersView(MyBaseView,View): def get(self,request,*args,**kwargs): return HttpResponse(‘GET‘) def post(self, request, *args, **kwargs): return HttpResponse(‘POST‘) def put(self, request, *args, **kwargs): return HttpResponse(‘PUT‘) def delete(self, request, *args, **kwargs): return HttpResponse(‘DELETE‘) 面试题: 1. django中间件 - process_request - process_view - process_response - process_exception - process_render_template 2. 使用中间件做过什么? - 权限 - 用户登录验证 - django的csrf是如何实现? process_view方法 - 检查视图是否被 @csrf_exempt (免除csrf认证) - 去请求体或cookie中获取token 3. 情况一: MIDDLEWARE = [ ‘django.middleware.security.SecurityMiddleware‘, ‘django.contrib.sessions.middleware.SessionMiddleware‘, ‘django.middleware.common.CommonMiddleware‘, ‘django.middleware.csrf.CsrfViewMiddleware‘, # 全站使用csrf认证 ‘django.contrib.auth.middleware.AuthenticationMiddleware‘, ‘django.contrib.messages.middleware.MessageMiddleware‘, ‘django.middleware.clickjacking.XFrameOptionsMiddleware‘, ] from django.views.decorators.csrf import csrf_exempt @csrf_exempt # 该函数无需csrf认证 def users(request): user_list = [‘alex‘,‘oldboy‘] return HttpResponse(json.dumps((user_list))) 情况二: MIDDLEWARE = [ ‘django.middleware.security.SecurityMiddleware‘, ‘django.contrib.sessions.middleware.SessionMiddleware‘, ‘django.middleware.common.CommonMiddleware‘, #‘django.middleware.csrf.CsrfViewMiddleware‘, # 全站不使用csrf认证 ‘django.contrib.auth.middleware.AuthenticationMiddleware‘, ‘django.contrib.messages.middleware.MessageMiddleware‘, ‘django.middleware.clickjacking.XFrameOptionsMiddleware‘, ] from django.views.decorators.csrf import csrf_exempt @csrf_protect # 该函数需csrf认证 def users(request): user_list = [‘alex‘,‘oldboy‘] return HttpResponse(json.dumps((user_list))) CBV小知识,csrf时需要使用 - @method_decorator(csrf_exempt) - 在dispatch方法中(单独方法无效) 方式一: from django.views.decorators.csrf import csrf_exempt,csrf_protect from django.utils.decorators import method_decorator class StudentsView(View): @method_decorator(csrf_exempt) def dispatch(self, request, *args, **kwargs): return super(StudentsView,self).dispatch(request, *args, **kwargs) def get(self,request,*args,**kwargs): print(‘get方法‘) return HttpResponse(‘GET‘) def post(self, request, *args, **kwargs): return HttpResponse(‘POST‘) def put(self, request, *args, **kwargs): return HttpResponse(‘PUT‘) def delete(self, request, *args, **kwargs): return HttpResponse(‘DELETE‘) 方式二: from django.views.decorators.csrf import csrf_exempt,csrf_protect from django.utils.decorators import method_decorator @method_decorator(csrf_exempt,name=‘dispatch‘) class StudentsView(View): def get(self,request,*args,**kwargs): print(‘get方法‘) return HttpResponse(‘GET‘) def post(self, request, *args, **kwargs): return HttpResponse(‘POST‘) def put(self, request, *args, **kwargs): return HttpResponse(‘PUT‘) def delete(self, request, *args, **kwargs): return HttpResponse(‘DELETE‘) 总结: - 本质,基于反射来实现 - 流程:路由,view,dispatch(反射) - 取消csrf认证(装饰器要加到dispatch方法上且method_decorator装饰) 扩展: - csrf - 基于中间件的process_view方法 - 装饰器给单独函数进行设置(认证或无需认证) 1. restful 规范(建议) a. 接口开发 urlpatterns = [ # url(r‘^admin/‘, admin.site.urls), url(r‘^get_order/‘, views.get_order), url(r‘^add_order/‘, views.add_order), url(r‘^del_order/‘, views.del_order), url(r‘^update_order/‘, views.update_order), ] def get_order(request): return HttpResponse(‘‘) def add_order(request): return HttpResponse(‘‘) def del_order(request): return HttpResponse(‘‘) def update_order(request): return HttpResponse(‘‘) b. restful 规范(建议) 1. 根据method不同做不同的操作,示例: 基于FBV: urlpatterns = [ url(r‘^order/‘, views.order), ] def order(request): if request.method == ‘GET‘: return HttpResponse(‘获取订单‘) elif request.method == ‘POST‘: return HttpResponse(‘创建订单‘) elif request.method == ‘PUT‘: return HttpResponse(‘更新订单‘) elif request.method == ‘DELETE‘: return HttpResponse(‘删除订单‘) 基于CBV: urlpatterns = [ url(r‘^order/‘, views.OrderView.as_view()), ] class OrderView(View): def get(self,request,*args,**kwargs): return HttpResponse(‘获取订单‘) def post(self,request,*args,**kwargs): return HttpResponse(‘创建订单‘) def put(self,request,*args,**kwargs): return HttpResponse(‘更新订单‘) def delete(self,request,*args,**kwargs): return HttpResponse(‘删除订单‘) c. 谈谈自己对restful api 规范的认识 10个规则 注意:推荐使用CBV 2. django rest framework框架 pip3 install djangorestframework a. 认证 - 仅使用: from django.views import View from rest_framework.views import APIView from rest_framework.authentication import BasicAuthentication from rest_framework import exceptions from rest_framework.request import Request class MyAuthentication(object): def authenticate(self,request): token = request._request.GET.get(‘token‘) # 获取用户名和密码,去数据校验 if not token: raise exceptions.AuthenticationFailed(‘用户认证失败‘) return ("alex",None) def authenticate_header(self,val): pass class DogView(APIView): authentication_classes = [MyAuthentication,] def get(self,request,*args,**kwargs): print(request) print(request.user) ret = { ‘code‘:1000, ‘msg‘:‘xxx‘ } return HttpResponse(json.dumps(ret),status=201) def post(self,request,*args,**kwargs): return HttpResponse(‘创建Dog‘) def put(self,request,*args,**kwargs): return HttpResponse(‘更新Dog‘) def delete(self,request,*args,**kwargs): return HttpResponse(‘删除Dog‘) - 源码流程: dispatch... *********************************************************************************** 内容: 1. 认证 2. 权限 3. 节流(访问频率控制) 4. 版本 内容: 1. 认证 a. 问题1:有些API需要用户登录成功之后,才能访问;有些无需登录就能访问。 b. 基本使用认证组件 解决: a. 创建两张表 b. 用户登录(返回token并保存到数据库) c. 认证流程原理 - 见图示 d. 再看一遍源码 1. 局部视图使用&全局使用 2. 匿名是request.user = None e. 内置认证类 1. 认证类,必须继承:from rest_framework.authentication import BaseAuthentication 2. 其他认证类:BasicAuthentication 梳理: 1. 使用 - 创建类:继承BaseAuthentication; 实现:authenticate方法 - 返回值: - None,我不管了,下一认证来执行。 - raise exceptions.AuthenticationFailed(‘用户认证失败‘) # from rest_framework import exceptions - (元素1,元素2) # 元素1赋值给request.user; 元素2赋值给request.auth - 局部使用 from rest_framework.authentication import BaseAuthentication,BasicAuthentication class UserInfoView(APIView): """ 订单相关业务 """ authentication_classes = [BasicAuthentication,] def get(self,request,*args,**kwargs): print(request.user) return HttpResponse(‘用户信息‘) - 全局使用: REST_FRAMEWORK = { # 全局使用的认证类 "DEFAULT_AUTHENTICATION_CLASSES":[‘api.utils.auth.FirstAuthtication‘,‘api.utils.auth.Authtication‘, ], # "UNAUTHENTICATED_USER":lambda :"匿名用户" "UNAUTHENTICATED_USER":None, # 匿名,request.user = None "UNAUTHENTICATED_TOKEN":None,# 匿名,request.auth = None } 2. 源码流程 - dispatch - 封装request - 获取定义的认证类(全局/局部),通过列表生成时创建对象。 - initial - perform_authentication request.user(内部循环....) 2. 权限 问题:不用视图不用权限可以访问 基本使用: class MyPermission(object): def has_permission(self,request,view): if request.user.user_type != 3: return False return True class OrderView(APIView): """ 订单相关业务(只有SVIP用户有权限) """ permission_classes = [MyPermission,] def get(self,request,*args,**kwargs): # request.user # request.auth self.dispatch ret = {‘code‘:1000,‘msg‘:None,‘data‘:None} try: ret[‘data‘] = ORDER_DICT except Exception as e: pass return JsonResponse(ret) 源码流程: - ... 梳理: 1. 使用 - 类,必须继承:BasePermission,必须实现:has_permission方法 from rest_framework.permissions import BasePermission class SVIPPermission(BasePermission): message = "必须是SVIP才能访问" def has_permission(self,request,view): if request.user.user_type != 3: return False return True - 返回值: - True, 有权访问 - False,无权访问 - 局部 class UserInfoView(APIView): """ 订单相关业务(普通用户、VIP) """ permission_classes = [MyPermission1, ] def get(self,request,*args,**kwargs): return HttpResponse(‘用户信息‘) - 全局 REST_FRAMEWORK = { "DEFAULT_PERMISSION_CLASSES":[‘api.utils.permission.SVIPPermission‘] } 2. 源码流程 3. 访问频率控制(节流) 问题:控制访问频率 import time VISIT_RECORD = {} class VisitThrottle(object): """60s内只能访问3次""" def __init__(self): self.history = None def allow_request(self,request,view): # 1. 获取用户IP remote_addr = request.META.get(‘REMOTE_ADDR‘) ctime = time.time() if remote_addr not in VISIT_RECORD: VISIT_RECORD[remote_addr] = [ctime,] return True history = VISIT_RECORD.get(remote_addr) self.history = history while history and history[-1] < ctime - 60: history.pop() if len(history) < 3: history.insert(0,ctime) return True # return True # 表示可以继续访问 # return False # 表示访问频率太高,被限制 def wait(self): """ 还需要等多少秒才能访问 :return: """ ctime = time.time() return 60 - (ctime - self.history[-1]) class AuthView(APIView): """ 用于用户登录认证 """ authentication_classes = [] permission_classes = [] throttle_classes = [VisitThrottle,] def post(self,request,*args,**kwargs): ret = {‘code‘:1000,‘msg‘:None} try: user = request._request.POST.get(‘username‘) pwd = request._request.POST.get(‘password‘) obj = models.UserInfo.objects.filter(username=user,password=pwd).first() if not obj: ret[‘code‘] = 1001 ret[‘msg‘] = "用户名或密码错误" # 为登录用户创建token token = md5(user) # 存在就更新,不存在就创建 models.UserToken.objects.update_or_create(user=obj,defaults={‘token‘:token}) ret[‘token‘] = token except Exception as e: ret[‘code‘] = 1002 ret[‘msg‘] = ‘请求异常‘ return JsonResponse(ret) 内置控制频率类: from rest_framework.throttling import BaseThrottle,SimpleRateThrottle class VisitThrottle(SimpleRateThrottle): scope = "Luffy" def get_cache_key(self, request, view): return self.get_ident(request) class UserThrottle(SimpleRateThrottle): scope = "LuffyUser" def get_cache_key(self, request, view): return request.user.username REST_FRAMEWORK = { # 全局使用的认证类 "DEFAULT_AUTHENTICATION_CLASSES":[‘api.utils.auth.FirstAuthtication‘,‘api.utils.auth.Authtication‘, ], # "DEFAULT_AUTHENTICATION_CLASSES":[‘api.utils.auth.FirstAuthtication‘, ], # "UNAUTHENTICATED_USER":lambda :"匿名用户" "UNAUTHENTICATED_USER":None, # 匿名,request.user = None "UNAUTHENTICATED_TOKEN":None,# 匿名,request.auth = None "DEFAULT_PERMISSION_CLASSES":[‘api.utils.permission.SVIPPermission‘], "DEFAULT_THROTTLE_CLASSES":["api.utils.throttle.UserThrottle"], "DEFAULT_THROTTLE_RATES":{ "Luffy":‘3/m‘, "LuffyUser":‘10/m‘, } } 梳理: a. 基本使用 - 类, 继承:BaseThrottle,实现:allow_request、wait - 类, 继承:SimpleRateThrottle,实现:get_cache_key、scope = "Luffy"(配置文件中的key) b. 局部 class AuthView(APIView): """ 用于用户登录认证 """ authentication_classes = [] permission_classes = [] throttle_classes = [VisitThrottle,] # ******************* def post(self,request,*args,**kwargs): ret = {‘code‘:1000,‘msg‘:None} try: user = request._request.POST.get(‘username‘) pwd = request._request.POST.get(‘password‘) obj = models.UserInfo.objects.filter(username=user,password=pwd).first() if not obj: ret[‘code‘] = 1001 ret[‘msg‘] = "用户名或密码错误" # 为登录用户创建token token = md5(user) # 存在就更新,不存在就创建 models.UserToken.objects.update_or_create(user=obj,defaults={‘token‘:token}) ret[‘token‘] = token except Exception as e: ret[‘code‘] = 1002 ret[‘msg‘] = ‘请求异常‘ return JsonResponse(ret) c. 全局 REST_FRAMEWORK = { # 全局使用的认证类 "DEFAULT_AUTHENTICATION_CLASSES":[‘api.utils.auth.FirstAuthtication‘,‘api.utils.auth.Authtication‘, ], # "DEFAULT_AUTHENTICATION_CLASSES":[‘api.utils.auth.FirstAuthtication‘, ], # "UNAUTHENTICATED_USER":lambda :"匿名用户" "UNAUTHENTICATED_USER":None, # 匿名,request.user = None "UNAUTHENTICATED_TOKEN":None,# 匿名,request.auth = None "DEFAULT_PERMISSION_CLASSES":[‘api.utils.permission.SVIPPermission‘], "DEFAULT_THROTTLE_CLASSES":["api.utils.throttle.UserThrottle"], "DEFAULT_THROTTLE_RATES":{ "Luffy":‘3/m‘, "LuffyUser":‘10/m‘, } } 内容: 1. 中间件 2. csrf原理 3. rest 10规范 4. 面向对象 5. django请求声明周期 6. django请求声明周期(包含rest framework框架) PS: dispatch 7. rest framework 认证流程(封装Request.user) 8. rest framework 权限流程 9. rest framework 节流流程 代码: 认证Demo, 权限Demo(用户类型不同,权限不同) 节流Demo(匿名,登录用) 三组件组合 *********************************************************************************2. Django声明周期 a. wsgi wsgi,是协议。 wsgiref,是实现了wsgi协议的一个模块。模块本质:一个socket服务端。(Django) werkzeug ,是实现了wsgi协议的一个模块。模块本质:一个socket服务端(Flask框架) tornado ,是实现了wsgi协议的一个模块。模块本质:一个socket服务端(Flask框架) uwsgi,是实现了wsgi协议的一个模块。模块本质:一个socket服务端。 3. Django生命周期(rest framework) 4. 中间件&装饰器 - 适用于所有请求批量做操作 场景: - 基于角色的权限控制 - 用户认证 - csrf,(说原理) - session(说原理) - 黑名单 - 日志记录 5. rest 框架原理 a. 认证流程 b. 权限 c. 节流 内容概要: 1. 版本 * 2. 解析器 * 3. 序列化 **** - 请求数据进行校验 - QuerySet进行序列化 4. 分页 ** 5. 路由 ** 6. 视图 ** 7. 渲染器 * 内容详细: 1. 版本 a. URL中通过GET传参() 自定义: http://127.0.0.1:8000/api/users/?version=v2 class ParamVersion(object): def determine_version(self, request, *args, **kwargs): version = request.query_params.get(‘version‘) return version class UsersView(APIView): versioning_class = ParamVersion def get(self,request,*args,**kwargs): #version = request._request.GET.get(‘version‘) #print(version) # version = request.query_params.get(‘version‘) # print(version) print(request.version) return HttpResponse(‘用户列表‘) b. 在URL中传参(推荐使用) urlpatterns = [ # url(r‘^admin/‘, admin.site.urls), url(r‘^(?P<version>[v1|v2]+)/users/$‘, views.UsersView.as_view()), ] REST_FRAMEWORK = { "DEFAULT_VERSIONING_CLASS":"rest_framework.versioning.URLPathVersioning", "DEFAULT_VERSION":‘v1‘, "ALLOWED_VERSIONS":[‘v1‘,‘v2‘], "VERSION_PARAM":‘version‘, } class UsersView(APIView): def get(self,request,*args,**kwargs): print(request.version) return HttpResponse(‘用户列表‘) 总结: 使用: 配置文件: REST_FRAMEWORK = { "DEFAULT_VERSIONING_CLASS":"rest_framework.versioning.URLPathVersioning", "DEFAULT_VERSION":‘v1‘, "ALLOWED_VERSIONS":[‘v1‘,‘v2‘], "VERSION_PARAM":‘version‘, } 路由系统: urlpatterns = [ # url(r‘^admin/‘, admin.site.urls), url(r‘^api/‘, include(‘api.urls‘)), ] urlpatterns = [ # url(r‘^admin/‘, admin.site.urls), url(r‘^(?P<version>[v1|v2]+)/users/$‘, views.UsersView.as_view(),name=‘uuu‘), ] 视图: class UsersView(APIView): def get(self,request,*args,**kwargs): # 1. 获取版本 print(request.version) # 2. 获取处理版本的对象 print(request.versioning_scheme) # 3. 反向生成URL(rest framework) u1 = request.versioning_scheme.reverse(viewname=‘uuu‘,request=request) print(u1) # 4. 反向生成URL u2 = reverse(viewname=‘uuu‘,kwargs={‘version‘:2}) print(u2) return HttpResponse(‘用户列表‘) 2. 解析器 前戏:django:request.POST/ request.body 1. 请求头要求: Content-Type: application/x-www-form-urlencoded PS: 如果请求头中的 Content-Type: application/x-www-form-urlencoded,request.POST中才有值(去request.body中解析数据)。 2. 数据格式要求: name=alex&age=18&gender=男 如: a. form表单提交 <form method...> input... </form> b. ajax提交 $.ajax({ url:... type:POST, data:{name:alex,age=18} # 内部转化 name=alex&age=18&gender=男 }) 情况一: $.ajax({ url:... type:POST, headers:{‘Content-Type‘:"application/json"} data:{name:alex,age=18} # 内部转化 name=alex&age=18&gender=男 }) # body有值;POST无 情况二: $.ajax({ url:... type:POST, headers:{‘Content-Type‘:"application/json"} data:JSON.stringfy({name:alex,age=18}) # {name:alex,age:18...} }) # body有值;POST无 # json.loads(request.body) rest_framework 解析器,对请求体数据进行解析 总结: 使用: 配置: REST_FRAMEWORK = { "DEFAULT_VERSIONING_CLASS":"rest_framework.versioning.URLPathVersioning", "DEFAULT_VERSION":‘v1‘, "ALLOWED_VERSIONS":[‘v1‘,‘v2‘], "VERSION_PARAM":‘version‘, "DEFAULT_PARSER_CLASSES":[‘rest_framework.parsers.JSONParser‘,‘rest_framework.parsers.FormParser‘] } 使用: class ParserView(APIView): # parser_classes = [JSONParser,FormParser,] """ JSONParser:表示只能解析content-type:application/json头 JSONParser:表示只能解析content-type:application/x-www-form-urlencoded头 """ def post(self,request,*args,**kwargs): """ 允许用户发送JSON格式数据 a. content-type: application/json b. {‘name‘:‘alex‘,age:18} :param request: :param args: :param kwargs: :return: """ """ 1. 获取用户请求 2. 获取用户请求体 3. 根据用户请求头 和 parser_classes = [JSONParser,FormParser,] 中支持的请求头进行比较 4. JSONParser对象去请求体 5. request.data """ print(request.data) return HttpResponse(‘ParserView‘) 源码流程 & 本质: a. 本质 请求头 :... 状态码: ... 请求方法:... b. 源码流程 - dispatch: request封装 - request.data 3. 序列化 序列化: 部分总结: 1. 写类 class RolesSerializer(serializers.Serializer): id = serializers.IntegerField() title = serializers.CharField() class UserInfoSerializer(serializers.ModelSerializer): class Meta: model = models.UserInfo # fields = "__all__" fields = [‘id‘,‘username‘,‘password‘,] 2. 字段 a. title = serializers.CharField(source="xxx.xxx.xx.xx") b. title = serializers.SerializerMethodField() class UserInfoSerializer(serializers.ModelSerializer): rls = serializers.SerializerMethodField() # 自定义显示 class Meta: model = models.UserInfo fields = [‘id‘,‘username‘,‘password‘,‘rls‘,] # 自定义方法 def get_rls(self, row): role_obj_list = row.roles.all() ret = [] for item in role_obj_list: ret.append({‘id‘:item.id,‘title‘:item.title}) return ret c. 自定义类 3. 自动序列化连表 class UserInfoSerializer(serializers.ModelSerializer): class Meta: model = models.UserInfo # fields = "__all__" fields = [‘id‘,‘username‘,‘password‘,‘group‘,‘roles‘] depth = 1 # 0 ~ 10 4. 生成链接 class UserInfoSerializer(serializers.ModelSerializer): group = serializers.HyperlinkedIdentityField(view_name=‘gp‘,lookup_field=‘group_id‘,lookup_url_kwarg=‘xxx‘) class Meta: model = models.UserInfo # fields = "__all__" fields = [‘id‘,‘username‘,‘password‘,‘group‘,‘roles‘] depth = 0 # 0 ~ 10 class UserInfoView(APIView): def get(self,request,*args,**kwargs): users = models.UserInfo.objects.all() ser = UserInfoSerializer(instance=users,many=True,context={‘request‘: request}) ret = json.dumps(ser.data, ensure_ascii=False) return HttpResponse(ret) 源码: 对象, Serializer类处理; QuerySet,ListSerializer类处理; # ser.data 请求数据校验: class XXValidator(object): def __init__(self, base): self.base = base def __call__(self, value): if not value.startswith(self.base): message = ‘标题必须以 %s 为开头。‘ % self.base raise serializers.ValidationError(message) def set_context(self, serializer_field): """ This hook is called by the serializer instance, prior to the validation call being made. """ # 执行验证之前调用,serializer_fields是当前字段对象 pass class UserGroupSerializer(serializers.Serializer): title = serializers.CharField(error_messages={‘required‘:‘标题不能为空‘},validators=[XXValidator(‘老男人‘),]) class UserGroupView(APIView): def post(self,request,*args,**kwargs): ser = UserGroupSerializer(data=request.data) if ser.is_valid(): print(ser.validated_data[‘title‘]) else: print(ser.errors) return HttpResponse(‘提交数据‘) 问: 自定义验证规则时,需要钩子函数?请问钩子函数如何写? ******************************************************************************** 内容: 0. 序列化源码 1. 分页 a. 分页,看第n页,每页显示n条数据; from rest_framework.pagination import PageNumberPagination class MyPageNumberPagination(PageNumberPagination): page_size = 2 page_size_query_param = ‘size‘ max_page_size = 5 page_query_param = ‘page‘ class Pager1View(APIView): def get(self,request,*args,**kwargs): # 获取所有数据 roles = models.Role.objects.all() # 创建分页对象 # pg = MyPageNumberPagination() pg = PageNumberPagination() # 在数据库中获取分页的数据 pager_roles = pg.paginate_queryset(queryset=roles,request=request,view=self) # 对数据进行序列化 ser = PagerSerialiser(instance=pager_roles, many=True) return Response(ser.data) # return pg.get_paginated_response(ser.data) b. 分页,在n个位置,向后查看n条数据; from api.utils.serializsers.pager import PagerSerialiser from rest_framework.response import Response from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination class MyLimitOffsetPagination(LimitOffsetPagination): default_limit = 2 limit_query_param = ‘limit‘ offset_query_param = ‘offset‘ max_limit = 5 class Pager1View(APIView): def get(self,request,*args,**kwargs): # 获取所有数据 roles = models.Role.objects.all() # 创建分页对象 # pg = MyLimitOffsetPagination() pg = LimitOffsetPagination() # 在数据库中获取分页的数据 pager_roles = pg.paginate_queryset(queryset=roles,request=request,view=self) # 对数据进行序列化 ser = PagerSerialiser(instance=pager_roles, many=True) return Response(ser.data) # return pg.get_paginated_response(ser.data) c. 加密分页,上一页和下一页。 from api.utils.serializsers.pager import PagerSerialiser from rest_framework.response import Response from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination,CursorPagination class MyCursorPagination(CursorPagination): cursor_query_param = ‘cursor‘ page_size = 2 ordering = ‘id‘ page_size_query_param = None max_page_size = None class Pager1View(APIView): def get(self,request,*args,**kwargs): # 获取所有数据 roles = models.Role.objects.all() # 创建分页对象 # pg = CursorPagination() pg = MyCursorPagination() # 在数据库中获取分页的数据 pager_roles = pg.paginate_queryset(queryset=roles,request=request,view=self) # 对数据进行序列化 ser = PagerSerialiser(instance=pager_roles, many=True) # return Response(ser.data) return pg.get_paginated_response(ser.data) 总结: 1. 数据量大的话,如何做分页? - 数据库性能相关? 2. 视图 a. 过去 class Pager1View(View): pass b. 现在 class Pager1View(APIView): # View pass c. 无用 from api.utils.serializsers.pager import PagerSerialiser from rest_framework.generics import GenericAPIView class View1View(GenericAPIView): # APIView queryset = models.Role.objects.all() serializer_class = PagerSerialiser pagination_class = PageNumberPagination def get(self,request,*args,**kwargs): # 获取数据 roles = self.get_queryset() # models.Role.objects.all() # [1, 1000,] [1,10] pager_roles = self.paginate_queryset(roles) # 序列化 ser = self.get_serializer(instance=pager_roles,many=True) return Response(ser.data) d. GenericViewSet(ViewSetMixin, generics.GenericAPIView): 路由: url(r‘^(?P<version>[v1|v2]+)/v1/$‘, views.View1View.as_view({‘get‘: ‘list‘})), 视图: from api.utils.serializsers.pager import PagerSerialiser from rest_framework.viewsets import GenericViewSet class View1View(GenericViewSet): queryset = models.Role.objects.all() serializer_class = PagerSerialiser pagination_class = PageNumberPagination def list(self, request, *args, **kwargs): # 获取数据 roles = self.get_queryset() # models.Role.objects.all() # [1, 1000,] [1,10] pager_roles = self.paginate_queryset(roles) # 序列化 ser = self.get_serializer(instance=pager_roles, many=True) return Response(ser.data) e. 路由系统: url(r‘^(?P<version>[v1|v2]+)/v1/$‘, views.View1View.as_view({‘get‘: ‘list‘,‘post‘:‘create‘})), url(r‘^(?P<version>[v1|v2]+)/v1/(?P<pk>\d+)/$‘, views.View1View.as_view({‘get‘: ‘retrieve‘,‘delete‘:‘destroy‘,‘put‘:‘update‘,‘patch‘:‘partial_update‘})), 视图: from api.utils.serializsers.pager import PagerSerialiser from rest_framework.viewsets import GenericViewSet,ModelViewSet from rest_framework.mixins import ListModelMixin,CreateModelMixin class View1View(ModelViewSet): queryset = models.Role.objects.all() serializer_class = PagerSerialiser pagination_class = PageNumberPagination PS: class View1View(CreateModelMixin,GenericViewSet): 总结: a. 增删改查 ModelViewSet b. 增删 CreateModelMixin,DestroyModelMixin GenericViewSet c. 复杂逻辑 GenericViewSet 或 APIView PS: 还债: GenericAPIView.get_object check_object_permissions has_object_permission 3. 路由 a. url(r‘^(?P<version>[v1|v2]+)/parser/$‘, views.ParserView.as_view()), b. url(r‘^(?P<version>[v1|v2]+)/v1/$‘, views.View1View.as_view({‘get‘: ‘list‘,‘post‘:‘create‘})), c. # http://127.0.0.1:8000/api/v1/v1/?format=json url(r‘^(?P<version>[v1|v2]+)/v1/$‘, views.View1View.as_view({‘get‘: ‘list‘,‘post‘:‘create‘})), # http://127.0.0.1:8000/api/v1/v1.json url(r‘^(?P<version>[v1|v2]+)/v1\.(?P<format>\w+)$‘, views.View1View.as_view({‘get‘: ‘list‘,‘post‘:‘create‘})), url(r‘^(?P<version>[v1|v2]+)/v1/(?P<pk>\d+)/$‘, views.View1View.as_view({‘get‘: ‘retrieve‘,‘delete‘:‘destroy‘,‘put‘:‘update‘,‘patch‘:‘partial_update‘})), url(r‘^(?P<version>[v1|v2]+)/v1/(?P<pk>\d+)\.(?P<format>\w+)$‘, views.View1View.as_view({‘get‘: ‘retrieve‘,‘delete‘:‘destroy‘,‘put‘:‘update‘,‘patch‘:‘partial_update‘})), d. from api import views from rest_framework import routers router = routers.DefaultRouter() router.register(r‘xxxxx‘, views.View1View) router.register(r‘rt‘, views.View1View) urlpatterns = [ url(r‘^(?P<version>[v1|v2]+)/‘, include(router.urls)), ] 4. 渲染 from rest_framework.renderers import JSONRenderer,BrowsableAPIRenderer class TestView(APIView): # renderer_classes = [JSONRenderer,BrowsableAPIRenderer] def get(self, request, *args, **kwargs): # 获取所有数据 roles = models.Role.objects.all() # 创建分页对象 # pg = CursorPagination() pg = MyCursorPagination() # 在数据库中获取分页的数据 pager_roles = pg.paginate_queryset(queryset=roles, request=request, view=self) # 对数据进行序列化 ser = PagerSerialiser(instance=pager_roles, many=True) return Response(ser.data) REST_FRAMEWORK = { "DEFAULT_VERSIONING_CLASS":"rest_framework.versioning.URLPathVersioning", "DEFAULT_VERSION":‘v1‘, "ALLOWED_VERSIONS":[‘v1‘,‘v2‘], "VERSION_PARAM":‘version‘, "DEFAULT_PARSER_CLASSES":[‘rest_framework.parsers.JSONParser‘,‘rest_framework.parsers.FormParser‘], "PAGE_SIZE":2, "DEFAULT_RENDERER_CLASSES":[ ‘rest_framework.renderers.JSONRenderer‘, ‘rest_framework.renderers.BrowsableAPIRenderer‘, ] } 5. django组件:contenttype********************************************************************************** 内容: 0. 序列化源码 1. 分页 a. 分页,看第n页,每页显示n条数据; from rest_framework.pagination import PageNumberPagination class MyPageNumberPagination(PageNumberPagination): page_size = 2 page_size_query_param = ‘size‘ max_page_size = 5 page_query_param = ‘page‘ class Pager1View(APIView): def get(self,request,*args,**kwargs): # 获取所有数据 roles = models.Role.objects.all() # 创建分页对象 # pg = MyPageNumberPagination() pg = PageNumberPagination() # 在数据库中获取分页的数据 pager_roles = pg.paginate_queryset(queryset=roles,request=request,view=self) # 对数据进行序列化 ser = PagerSerialiser(instance=pager_roles, many=True) return Response(ser.data) # return pg.get_paginated_response(ser.data) b. 分页,在n个位置,向后查看n条数据; from api.utils.serializsers.pager import PagerSerialiser from rest_framework.response import Response from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination class MyLimitOffsetPagination(LimitOffsetPagination): default_limit = 2 limit_query_param = ‘limit‘ offset_query_param = ‘offset‘ max_limit = 5 class Pager1View(APIView): def get(self,request,*args,**kwargs): # 获取所有数据 roles = models.Role.objects.all() # 创建分页对象 # pg = MyLimitOffsetPagination() pg = LimitOffsetPagination() # 在数据库中获取分页的数据 pager_roles = pg.paginate_queryset(queryset=roles,request=request,view=self) # 对数据进行序列化 ser = PagerSerialiser(instance=pager_roles, many=True) return Response(ser.data) # return pg.get_paginated_response(ser.data) c. 加密分页,上一页和下一页。 from api.utils.serializsers.pager import PagerSerialiser from rest_framework.response import Response from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination,CursorPagination class MyCursorPagination(CursorPagination): cursor_query_param = ‘cursor‘ page_size = 2 ordering = ‘id‘ page_size_query_param = None max_page_size = None class Pager1View(APIView): def get(self,request,*args,**kwargs): # 获取所有数据 roles = models.Role.objects.all() # 创建分页对象 # pg = CursorPagination() pg = MyCursorPagination() # 在数据库中获取分页的数据 pager_roles = pg.paginate_queryset(queryset=roles,request=request,view=self) # 对数据进行序列化 ser = PagerSerialiser(instance=pager_roles, many=True) # return Response(ser.data) return pg.get_paginated_response(ser.data) 总结: 1. 数据量大的话,如何做分页? - 数据库性能相关? 2. 视图 a. 过去 class Pager1View(View): pass b. 现在 class Pager1View(APIView): # View pass c. 无用 from api.utils.serializsers.pager import PagerSerialiser from rest_framework.generics import GenericAPIView class View1View(GenericAPIView): # APIView queryset = models.Role.objects.all() serializer_class = PagerSerialiser pagination_class = PageNumberPagination def get(self,request,*args,**kwargs): # 获取数据 roles = self.get_queryset() # models.Role.objects.all() # [1, 1000,] [1,10] pager_roles = self.paginate_queryset(roles) # 序列化 ser = self.get_serializer(instance=pager_roles,many=True) return Response(ser.data) d. GenericViewSet(ViewSetMixin, generics.GenericAPIView): 路由: url(r‘^(?P<version>[v1|v2]+)/v1/$‘, views.View1View.as_view({‘get‘: ‘list‘})), 视图: from api.utils.serializsers.pager import PagerSerialiser from rest_framework.viewsets import GenericViewSet class View1View(GenericViewSet): queryset = models.Role.objects.all() serializer_class = PagerSerialiser pagination_class = PageNumberPagination def list(self, request, *args, **kwargs): # 获取数据 roles = self.get_queryset() # models.Role.objects.all() # [1, 1000,] [1,10] pager_roles = self.paginate_queryset(roles) # 序列化 ser = self.get_serializer(instance=pager_roles, many=True) return Response(ser.data) e. 路由系统: url(r‘^(?P<version>[v1|v2]+)/v1/$‘, views.View1View.as_view({‘get‘: ‘list‘,‘post‘:‘create‘})), url(r‘^(?P<version>[v1|v2]+)/v1/(?P<pk>\d+)/$‘, views.View1View.as_view({‘get‘: ‘retrieve‘,‘delete‘:‘destroy‘,‘put‘:‘update‘,‘patch‘:‘partial_update‘})), 视图: from api.utils.serializsers.pager import PagerSerialiser from rest_framework.viewsets import GenericViewSet,ModelViewSet from rest_framework.mixins import ListModelMixin,CreateModelMixin class View1View(ModelViewSet): queryset = models.Role.objects.all() serializer_class = PagerSerialiser pagination_class = PageNumberPagination PS: class View1View(CreateModelMixin,GenericViewSet): 总结: a. 增删改查 ModelViewSet b. 增删 CreateModelMixin,DestroyModelMixin GenericViewSet c. 复杂逻辑 GenericViewSet 或 APIView PS: 还债: GenericAPIView.get_object check_object_permissions has_object_permission 3. 路由 a. url(r‘^(?P<version>[v1|v2]+)/parser/$‘, views.ParserView.as_view()), b. url(r‘^(?P<version>[v1|v2]+)/v1/$‘, views.View1View.as_view({‘get‘: ‘list‘,‘post‘:‘create‘})), c. # http://127.0.0.1:8000/api/v1/v1/?format=json url(r‘^(?P<version>[v1|v2]+)/v1/$‘, views.View1View.as_view({‘get‘: ‘list‘,‘post‘:‘create‘})), # http://127.0.0.1:8000/api/v1/v1.json url(r‘^(?P<version>[v1|v2]+)/v1\.(?P<format>\w+)$‘, views.View1View.as_view({‘get‘: ‘list‘,‘post‘:‘create‘})), url(r‘^(?P<version>[v1|v2]+)/v1/(?P<pk>\d+)/$‘, views.View1View.as_view({‘get‘: ‘retrieve‘,‘delete‘:‘destroy‘,‘put‘:‘update‘,‘patch‘:‘partial_update‘})), url(r‘^(?P<version>[v1|v2]+)/v1/(?P<pk>\d+)\.(?P<format>\w+)$‘, views.View1View.as_view({‘get‘: ‘retrieve‘,‘delete‘:‘destroy‘,‘put‘:‘update‘,‘patch‘:‘partial_update‘})), d. from api import views from rest_framework import routers router = routers.DefaultRouter() router.register(r‘xxxxx‘, views.View1View) router.register(r‘rt‘, views.View1View) urlpatterns = [ url(r‘^(?P<version>[v1|v2]+)/‘, include(router.urls)), ] 4. 渲染 from rest_framework.renderers import JSONRenderer,BrowsableAPIRenderer class TestView(APIView): # renderer_classes = [JSONRenderer,BrowsableAPIRenderer] def get(self, request, *args, **kwargs): # 获取所有数据 roles = models.Role.objects.all() # 创建分页对象 # pg = CursorPagination() pg = MyCursorPagination() # 在数据库中获取分页的数据 pager_roles = pg.paginate_queryset(queryset=roles, request=request, view=self) # 对数据进行序列化 ser = PagerSerialiser(instance=pager_roles, many=True) return Response(ser.data) REST_FRAMEWORK = { "DEFAULT_VERSIONING_CLASS":"rest_framework.versioning.URLPathVersioning", "DEFAULT_VERSION":‘v1‘, "ALLOWED_VERSIONS":[‘v1‘,‘v2‘], "VERSION_PARAM":‘version‘, "DEFAULT_PARSER_CLASSES":[‘rest_framework.parsers.JSONParser‘,‘rest_framework.parsers.FormParser‘], "PAGE_SIZE":2, "DEFAULT_RENDERER_CLASSES":[ ‘rest_framework.renderers.JSONRenderer‘, ‘rest_framework.renderers.BrowsableAPIRenderer‘, ] } 5. django组件:contenttype
标签:普通用户 get 获取 分页 outer war 角色 序列 click
原文地址:https://www.cnblogs.com/BensonChang/p/9245727.html