Django - rest - framework - 下
一、视图三部曲
https://www.cnblogs.com/wupeiqi/articles/7805382.html
使用混合(mixins)
之前得视图部分
# urls.py from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^publishes/$', views.PublishView.as_view(),name="publish"), url(r'^publishes/(?P<pk>\d+)/$', views.PublishDetailView.as_view(),name="detail_publish"), url(r"^books/$", views.BookView.as_view(),name="books"), url(r'^books/(?P<pk>\d+)/$',views.BookDetailView.as_view(),name="detail_book") ] ------------------------------------------------------ # views.py from rest_framework.views import APIView, Response from app01.serializers import * class PublishView(APIView): def get(self, request): publish_list = Publish.objects.all() ret = PublishModelSerializers(publish_list, many=True) return Response(ret.data) def post(self, request): ps = PublishModelSerializers(data=request.data) if ps.is_valid(): ps.save() return Response(ps.data) else: return Response(ps.errors) class PublishDetailView(APIView): def get(self,request,pk): publish = Publish.objects.filter(pk=pk).first() ps = PublishModelSerializers(publish) return Response(ps.data) def put(self,request,pk): publish = Publish.objects.filter(pk=pk).first() ps = PublishModelSerializers(publish,data=request.data) if ps.is_valid(): ps.save() return Response(ps.data) else: return Response(ps.errors) def delete(self,request,pk): Publish.objects.filter(pk=pk).delete() return Response() class BookView(APIView): def get(self, request): book_list = Book.objects.all() ret = BookModelSerializers(book_list, many=True,context={"request":request}) return Response(ret.data) def post(self, request): bms = BookModelSerializers(data=request.data, many=False,context={"request":request}) if bms.is_valid(): bms.save() return Response(bms.data) else: return Response(bms.errors) class BookDetailView(APIView): def get(self,request,pk): book = Book.objects.filter(pk=pk).first() # 序列化 bms = BookModelSerializers(book,context={"request":request}) return Response(bms.data) def put(self,request,pk): book = Book.objects.filter(pk=pk).first() bms = BookModelSerializers(book,data=request.data,context={"request":request}) if bms.is_valid(): bms.save() return Response(bms.data) else: return Response(bms.errors) def delete(self,reqeust,pk): Book.objects.filter(pk=pk).delete() return Response() --------------------------------------------------- # serializers.py # -*- coding:utf-8 -*- from .models import * from rest_framework import serializers class PublishModelSerializers(serializers.ModelSerializer): class Meta: model = Publish fields = "__all__" class BookModelSerializers(serializers.ModelSerializer): class Meta: model = Book fields = "__all__"
from django.db import models # Create your models here. class Book(models.Model): title = models.CharField(max_length=32) price = models.IntegerField() pub_date = models.DateField() publish = models.ForeignKey("Publish") authors = models.ManyToManyField("Author") def __str__(self): return self.title class Publish(models.Model): name = models.CharField(max_length=32) email = models.EmailField() def __str__(self): return self.name class Author(models.Model): name = models.CharField(max_length=32) age = models.IntegerField() def __str__(self): return self.name
1. mixin类编写视图
from rest_framework import mixins, generics
mixins.ListModelMixin, mixins.CreateModelMixin,
mixins.RetrieveModelMixin, mixins.UpdateModelMixin, mixins.DestroyModelMixin,
generics.GenericAPIView
url(r'^authors/$',views.AuthorView.as_view(),name="author"), url(r'^authors/(?P<pk>\d+)',views.AuthorDetailView.as_view(),name="detail_author"), ----------------------------------------- ######################### mixin类编写视图 ############################## from rest_framework import mixins, generics class AuthorView(mixins.ListModelMixin, mixins.CreateModelMixin, generics.GenericAPIView): queryset = Author.objects.all() serializer_class = AuthorModelSerializers def get(self, request, *args, **kwargs): return self.list(request, *args, **kwargs) def post(self, request, *args, **kwargs): return self.create(request, *args, **kwargs) class AuthorDetailView(mixins.RetrieveModelMixin, mixins.UpdateModelMixin, mixins.DestroyModelMixin, generics.GenericAPIView): queryset = Author.objects.all() serializer_class = AuthorModelSerializers def get(self, request, *args, **kwargs): return self.retrieve(request, *args, **kwargs) def put(self, request, *args, **kwargs): return self.update(request, *args, **kwargs) def delete(self, request, *args, **kwargs): return self.destroy(request, *args, **kwargs) ------------------------------------------------ class AuthorModelSerializers(serializers.ModelSerializer): class Meta: model = Author fields = "__all__"
2. 使用通用的基于类的视图
from rest_framework import generics
generics.ListCreateAPIView
generics.RetrieveUpdateDestroyAPIView
通过使用mixin类,我们使用更少的代码重写了这些视图,但我们还可以再进一步。REST框架提供了一组已经混合好(mixed-in)的通用视图,我们可以使用它来简化我们的views.py
模块。
######################### 使用通用得基于类得视图 ############################## from rest_framework import generics class AuthorView(generics.ListCreateAPIView): queryset = Author.objects.all() serializer_class = AuthorModelSerializers class AuthorDetailView(generics.RetrieveUpdateDestroyAPIView): queryset = Author.objects.all() serializer_class = AuthorModelSerializers
3. viewsets.ModelViewSet
views.AuthorModelView.as_view({"get": "list", "post": "create"})
views.AuthorModelView.as_view({"get": "retrieve", "put": "update", "delete": "destroy"})
from rest_framework import viewsets
viewsets.ModelViewSet
url(r'^authors/$', views.AuthorModelView.as_view({"get": "list", "post": "create"}), name="author"), url(r'^authors/(?P<pk>\d+)', views.AuthorModelView.as_view({"get": "retrieve", "put": "update", "delete": "destroy"}), name="detail_author"), --------------------------------------------------- ######################### viewsets.ModelViewSet ############################## from rest_framework import viewsets class AuthorModelView(viewsets.ModelViewSet): queryset = Author.objects.all() serializer_class = AuthorModelSerializers
# 可重写,覆盖!
# def list(self,request,*args,**kwargs):pass
效果:
get post get put delete 都可访问!
http://www.cnblogs.com/yuanchenqi/articles/8719520.html 视图三部曲 5中方法: 查(全部) 查(单条) 增 删 改 逻辑封装起来了 ----------------------------------- class AuthorModelView(viewsets.ModelViewSet): queryset = Author.objects.all() serializer_class = AuthorModelSerializers (1):url(r'^authors/$', views.AuthorModelView.as_view({"get":"list","post":"create"}), name='author'), (2):url(r'^authors/$', ViewSetMixin.as_view({"get":"list","post":"create"}), name='author'), (3):url(r'^authors/$', ViewsetMixin.View, name='author'), 一旦用户 get 方式 访问 authors: ViewsetMixin.View(): for method, action in actions.items(): # {"get":"list","post":"create"} handler = getattr(self, action) # self.list self.create setattr(self, method, handler) # self.get = self.list self.post = self.create # getattr(self,"get") # self.list # getattr(self,"post") # self.create return self.dispatch() APIView.dispatch(): if request.method.lower() in self.http_method_names: handler = getattr(self,request.method.lower()) response = handler(request,*args,**kwargs) # self.list() return response (ViewSetMixin)
二、认证组件
生成随机字符串
import hashlib, time def get_random_str(user): """ 生成随机 字符串 """ ctime = str(time.time()) md5 = hashlib.md5(bytes(user,encoding='utf-8')) md5.update(bytes(ctime,encoding="utf-8")) return md5.hexdigest()
update_or_create
# update_or_create Token.objects.update_or_create(user=user,defaults={"token":random_str})
返回json
# import json # from django.shortcuts import HttpResponse # return HttpResponse(json.dumps(res,ensure_ascii=False))
# from django.http import JsonResponse # return JsonResponse(res) return Response(res)
登录,生成随机token
url(r'^login/$', views.LoginView.as_view(), name="login") --------------------------------------------- import hashlib, time def get_random_str(user): """ 生成随机 字符串 """ ctime = str(time.time()) md5 = hashlib.md5(bytes(user,encoding='utf-8')) md5.update(bytes(ctime,encoding="utf-8")) return md5.hexdigest() class LoginView(APIView): def post(self,request): name = request.data.get("name") pwd = request.data.get("pwd") user = User.objects.filter(name=name,pwd=pwd).first() res = {"state_code":1000,"msg":None} if user: random_str = get_random_str(user.name) # update_or_create Token.objects.update_or_create(user=user,defaults={"token":random_str}) res["token"] = random_str else: res["state_code"] = 1001 # 错误状态码 res["msg"] = "用户名或密码错误" # import json # from django.shortcuts import HttpResponse # return HttpResponse(json.dumps(res,ensure_ascii=False)) # from django.http import JsonResponse # return JsonResponse(res) return Response(res) -------------------------------------------------------- # models.py class User(models.Model): name = models.CharField(max_length=32) pwd = models.CharField(max_length=32) class Token(models.Model): user = models.OneToOneField("User") token = models.CharField(max_length=128) def __str__(self): return self.token
效果图:
登录验证 - 局部
authentication_classes = [TokenAuth]
from rest_framework import exceptions
from rest_framework.authentication import BaseAuthentication
def authenticate(self,request):
... ...
if not token_obj:
raise exceptions.AuthenticationFailed("验证失败")
return (token_obj.user.name, token_obj)
from rest_framework import exceptions # class TokenAuth(object): # def authenticate(self,request): # token = request.GET.get("token") # token_obj = Token.objects.filter(token=token).first() # if not token_obj: # raise exceptions.AuthenticationFailed("验证失败") # # return (token_obj.user.name, token_obj) # # def authenticate_header(self,request): # pass from rest_framework.authentication import BaseAuthentication class TokenAuth(BaseAuthentication): def authenticate(self,request): token = request.GET.get("token") token_obj = Token.objects.filter(token=token).first() if not token_obj: raise exceptions.AuthenticationFailed("验证失败") return (token_obj.user.name, token_obj) class BookView(APIView): authentication_classes = [TokenAuth] def get(self, request): book_list = Book.objects.all() ret = BookModelSerializers(book_list, many=True, context={"request": request}) return Response(ret.data) def post(self, request): bms = BookModelSerializers(data=request.data, many=False, context={"request": request}) if bms.is_valid(): bms.save() return Response(bms.data) else: return Response(bms.errors)
登录验证 - 全局
settings 配置
'DEFAULT_AUTHENTICATION_CLASSES': ['app01.utils.TokenAuth']
# settings.py REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ['app01.utils.TokenAuth'] } ------------------------------------------- # app01.utils from .models import * from rest_framework import exceptions from rest_framework.authentication import BaseAuthentication class TokenAuth(BaseAuthentication): def authenticate(self,request): token = request.GET.get("token") token_obj = Token.objects.filter(token=token).first() if not token_obj: raise exceptions.AuthenticationFailed("验证失败") return (token_obj.user.name, token_obj) -------------------------------------------- # views.py class BookView(APIView): def get(self, request): book_list = Book.objects.all() ret = BookModelSerializers(book_list, many=True, context={"request": request}) return Response(ret.data) def post(self, request): bms = BookModelSerializers(data=request.data, many=False, context={"request": request}) if bms.is_valid(): bms.save() return Response(bms.data) else: return Response(bms.errors)
-----------------------------------------
class AuthorModelView(viewsets.ModelViewSet):
authentication_classes = [] # 加上这个,前提是全局有认证;加上这个,就走自己得,不认证了,自己没有,才走全局配置得!
queryset = Author.objects.all()
serializer_class = AuthorModelSerializers
效果图:
三、权限组件
权限 - 局部
permission_classes = [SVIPPermission]
has_permission(self,request,view):pass # 固定得写法,根据源码来写得!
authentication_classes = [] # 登录页面 不需要验证,在全局配置得前提下
class AuthorModelView(viewsets.ModelViewSet): authentication_classes = [TokenAuth] permission_classes = [SVIPPermission] queryset = Author.objects.all() serializer_class = AuthorModelSerializers ----------------------------------------------
# app01.utils.SVIPPermission
class SVIPPermission(object): message = "只有超级用户才能访问" def has_permission(self,request,view): username = request.user user_type = User.objects.filter(name=username).first().user_type if user_type == 3: return True else: return False ---------------------------------------------- class LoginView(APIView): authentication_classes = [] ... ...
权限 - 全局
settings配置:
'DEFAULT_PERMISSION_CLASSES': ['app01.utils.SVIPPermission']
# settings.py
REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ['app01.utils.TokenAuth'], 'DEFAULT_PERMISSION_CLASSES': ['app01.utils.SVIPPermission'] }
效果图:
四、频率组件
局部视图throttle
class BookView(APIView): # authentication_classes = [TokenAuth] # permission_classes = [SVIPPermission] throttle_classes = [VisitRateThrottle] 。。。 。。。 ----------------------------------------------- from rest_framework.throttling import BaseThrottle VISIT_RECORD={} class VisitThrottle(BaseThrottle): def __init__(self): self.history=None def allow_request(self,request,view): remote_addr = request.META.get('REMOTE_ADDR') print(remote_addr) import time 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 else: return False def wait(self): import time ctime=time.time() return 60-(ctime-self.history[-1])
全局视图throttle
REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ['app01.utils.TokenAuth'], 'DEFAULT_PERMISSION_CLASSES': ['app01.utils.SVIPPermission'], 'DEFAULT_THROTTLE_CLASSES': ['app01.utils.VisitThrottle'], }
内置throttle类
REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ['app01.utils.TokenAuth'], 'DEFAULT_PERMISSION_CLASSES': ['app01.utils.SVIPPermission'], 'DEFAULT_THROTTLE_CLASSES': ['app01.utils.VisitThrottle'], "DEFAULT_THROTTLE_RATES": { "visit_rate": "1/m", } } ------------------------------------ from rest_framework.throttling import SimpleRateThrottle class VisitThrottle(SimpleRateThrottle): scope="visit_rate" def get_cache_key(self, request, view): return self.get_ident(request)
http://www.cnblogs.com/yuanchenqi/articles/8719520.html
五、解析器
from rest_framework.parsers import JSONParser,FormParser,MultiPartParser,FileUploadParser """ 默认得是 JSONParser FormParser MultiPartParser """ class BookView(APIView): parser_classes = [JSONParser,FormParser] ...
request类
django的request类和rest-framework的request类的源码解析
局部视图
from rest_framework.parsers import JSONParser,FormParser class PublishViewSet(generics.ListCreateAPIView): parser_classes = [FormParser,JSONParser] queryset = Publish.objects.all() serializer_class = PublshSerializers def post(self, request, *args, **kwargs): print("request.data",request.data) return self.create(request, *args, **kwargs)
全局视图
REST_FRAMEWORK={ "DEFAULT_AUTHENTICATION_CLASSES":["app01.service.auth.Authentication",], "DEFAULT_PERMISSION_CLASSES":["app01.service.permissions.SVIPPermission",], "DEFAULT_THROTTLE_CLASSES":["app01.service.throttles.VisitThrottle",], "DEFAULT_THROTTLE_RATES":{ "visit_rate":"5/m", }, "DEFAULT_PARSER_CLASSES":['rest_framework.parsers.FormParser',] }
六、url路由控制
url(r'',include(routers.urls)),
from rest_framework import routers
routers = routers.DefaultRouter()
routers.register("authors",views.AuthorModelView)
# urls.py from django.conf.urls import url,include from django.contrib import admin from app01 import views from rest_framework import routers routers = routers.DefaultRouter() routers.register("authors",views.AuthorModelView) urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^publishes/$', views.PublishView.as_view(), name="publish"), url(r'^publishes/(?P<pk>\d+)/$', views.PublishDetailView.as_view(), name="detail_publish"), url(r"^books/$", views.BookView.as_view(), name="books"), url(r'^books/(?P<pk>\d+)/$', views.BookDetailView.as_view(), name="detail_book"), # url(r'^authors/$',views.AuthorView.as_view(),name="author"), # url(r'^authors/(?P<pk>\d+)',views.AuthorDetailView.as_view(),name="detail_author"), # url(r'^authors/$', views.AuthorModelView.as_view({"get": "list", "post": "create"}), name="author"), # url(r'^authors/(?P<pk>\d+)', # views.AuthorModelView.as_view({"get": "retrieve", "put": "update", "delete": "destroy"}), name="detail_author"), url(r'',include(routers.urls)), url(r'^login/$', views.LoginView.as_view(), name="login") ] ------------------------------------------ # views.py from rest_framework import viewsets class AuthorModelView(viewsets.ModelViewSet): queryset = Author.objects.all() serializer_class = AuthorModelSerializers
效果图
七、分页
pnp = MyPageNumberPagination()
books_page = pnp.paginate_queryset(book_list,request,self)
from rest_framework.pagination import PageNumberPagination, LimitOffsetPagination class MyPageNumberPagination(PageNumberPagination): page_size = 2 page_query_param = "page" page_size_query_param = "size" max_page_size = 2 # 限制 size 得大小 不能超过多少!! class MyLimitOffsetPagination(LimitOffsetPagination): default_limit = 1 --------------------------- class BookView(APIView):def get(self, request): book_list = Book.objects.all() pnp = MyPageNumberPagination() # pnp = MyLimitOffsetPagination() books_page = pnp.paginate_queryset(book_list,request,self) # ret = BookModelSerializers(book_list, many=True, context={"request": request}) ret = BookModelSerializers(books_page, many=True) # return Response(ret.data)
return pnp.get_paginated_response(ret.data)
from rest_framework import viewsets class AuthorModelView(viewsets.ModelViewSet): queryset = Author.objects.all() serializer_class = AuthorModelSerializers pagination_class = MyPageNumberPagination
效果图
day99 1 CBV 2 APIView class BookView(APIView):pass url(r'^books/$', views.BookView.as_view(),name="books"), url(r'^books/$', View类下的view,name="books"), 一旦访问books/: view(request)======APIView类下的dispatch()====请求方式对应的示例方法() 3 def dispatch(): #一 初始化操作 # (1) 构建新的request: self.request=self.initial_request() # self.request._request # self.request.GET # self.request.data # (2) 执行组件 # 认证,权限,频率 # 认证:request.user self.initial(request, *args, **kwargs) ==== # 认证组件 self.perform_authentication(request) ==== request.user ===== for authenticator in self.authenticators: # [TokenAuth(),] try: user_auth_tuple = authenticator.authenticate(self) except exceptions.APIException: self._not_authenticated() raise if user_auth_tuple is not None: self._authenticator = authenticator self.user, self.auth = user_auth_tuple return # 权限组件 self.check_permissions(request) =========== for permission in self.get_permissions(): if not permission.has_permission(request, self): self.permission_denied( request, message=getattr(permission, 'message', None) ) # 频率组件 self.check_throttles(request) ============= for throttle in self.get_throttles(): # [VisitRateThrottle(),] if not throttle.allow_request(request, self): self.throttled(request, throttle.wait()) # 受限制 # 分发 if request.method.lower() in self.http_method_names: handler = getattr(self,request.method.lower(), self.http_method_not_allowed) response = handler(request, *args, **kwargs) return response 4 序列化组件 class PublishSerializers(serializers.Serializer): name = serializers.CharField() email = serializers.CharField() class PublishModelSerializers(serializers.ModelSerializer): class Meta: model=Publish fields="__all__" # queryset或者model对象-------------》json数据 ps=PublishSerializers(queryset,many=True) ps.data # [{},{},{}] ps=PublishSerializers(model_obj,many=False) ps.data # {} # json数据-------》记录 # 添加操作 ps=PublishSerializers(data=request.data) if ps.is_valid(): ps.save() # create # 更新操作 ps=PublishSerializers(model_obj,data=request.data) if ps.is_valid(): ps.save() # update 5 视图组件 # 版本1: # Book表 class BookView(APIView): def get(self,request): book_list=Book.objects.all() bs=BookModelSerializers(book_list,many=True,context={'request': request}) return Response(bs.data) def post(self,request): # post请求的数据 bs=BookModelSerializers(data=request.data) if bs.is_valid(): print(bs.validated_data) bs.save()# create方法 return Response(bs.data) else: return Response(bs.errors) class BookDetailView(APIView): def get(self,request,id): book=Book.objects.filter(pk=id).first() bs=BookModelSerializers(book,context={'request': request}) return Response(bs.data) def put(self,request,id): book=Book.objects.filter(pk=id).first() bs=BookModelSerializers(book,data=request.data) if bs.is_valid(): bs.save() return Response(bs.data) else: return Response(bs.errors) def delete(self,request,id): Book.objects.filter(pk=id).delete() return Response() # 版本2:mixIn from rest_framework import mixins from rest_framework import generics class AuthorView(mixins.ListModelMixin,mixins.CreateModelMixin,generics.GenericAPIView): queryset=Author.objects.all() serializer_class =AuthorModelSerializers def get(self,request, *args, **kwargs): return self.list(request, *args, **kwargs) def post(self,request, *args, **kwargs): return self.create(request, *args, **kwargs) class AuthorDetailView(mixins.RetrieveModelMixin,mixins.DestroyModelMixin,mixins.UpdateModelMixin,generics.GenericAPIView): queryset = Author.objects.all() serializer_class = AuthorModelSerializers def get(self,request,*args, **kwargs): return self.retrieve(request,*args, **kwargs) def delete(self,request,*args, **kwargs): return self.destroy(request,*args, **kwargs) def put(self,request,*args, **kwargs): return self.retrieve(request,*args, **kwargs) # 版本3:基于通用类 from rest_framework import mixins from rest_framework import generics class AuthorView(generics.ListCreateAPIView): queryset=Author.objects.all() serializer_class =AuthorModelSerializers class AuthorDetailView(generics.RetrieveUpdateDestroyAPIView): queryset = Author.objects.all() serializer_class = AuthorModelSerializers # 版本4 class AuthorModelView(viewsets.ModelViewSet): queryset = Author.objects.all() serializer_class = AuthorModelSerializers url(r'^authors/$', views.AuthorModelView.as_view({"get":"list","post":"create"}),name="author"), url(r'^authors/(?P<pk>\d+)/$', views.AuthorModelView.as_view({"get":"retrieve","put" 流程: url(r'^authors/$', views.AuthorModelView.as_view({"get":"list","post":"create"}),name="author"), url(r'^authors/$', ViewSetMixin.as_view({"get":"list","post":"create"}),name="author"), url(r'^authors/$', ViewSetMixin类下的view), 一旦访问 /authors/: ViewSetMixin def view(): for method, action in actions.items(): # {"get":"list","post":"create"} handler = getattr(self, action) # self.list self.create setattr(self, method, handler) self.dispatch(request, *args, **kwargs) APIView类下的self.dispatch # 分发 if request.method.lower() in self.http_method_names: handler = getattr(self,request.method.lower(), self.http_method_not_allowed) response = handler(request, *args, **kwargs) # self.list() return response 6 认证权限频率 组件 request.META: {'ALLUSERSPROFILE': 'C:\\ProgramData', 'APPDATA': 'C:\\Users\\Administrator\\AppData\\Roaming', 'COMMONPROGRAMFILES': 'C:\\Program Files\\Common Files', 'COMMONPROGRAMFILES(X86)': 'C:\\Program Files (x86)\\Common Files', 'COMMONPROGRAMW6432': 'C:\\Program Files\\Common Files', 'COMPUTERNAME': 'PC201712041709', 'COMSPEC': 'C:\\Windows\\system32\\cmd.exe', 'DJANGO_SETTINGS_MODULE': 'restdemo.settings', 'FP_NO_HOST_CHECK': 'NO', 'HOMEDRIVE': 'C:', 'HOMEPATH': '\\Users\\Administrator', 'LOCALAPPDATA': 'C:\\Users\\Administrator\\AppData\\Local', 'LOGONSERVER': '\\\\PC201712041709', 'NUMBER_OF_PROCESSORS': '4', 'OS': 'Windows_NT', 'PATH': 'C:\\Windows\\system32;C:\\Windows;C:\\Windows\\System32\\Wbem;C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\;C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python36;C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python36\\Scripts;C:\\Python27;E:\\MySQL Server 5.6\\bin;C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python36\\Scripts\\;C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python36\\;C:\\Users\\Administrator\\AppData\\Local\\atom\\bin', 'PATHEXT': '.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC', 'PROCESSOR_ARCHITECTURE': 'AMD64', 'PROCESSOR_IDENTIFIER': 'Intel64 Family 6 Model 60 Stepping 3, GenuineIntel', 'PROCESSOR_LEVEL': '6', 'PROCESSOR_REVISION': '3c03', 'PROGRAMDATA': 'C:\\ProgramData', 'PROGRAMFILES': 'C:\\Program Files', 'PROGRAMFILES(X86)': 'C:\\Program Files (x86)', 'PROGRAMW6432': 'C:\\Program Files', 'PSMODULEPATH': 'C:\\Windows\\system32\\WindowsPowerShell\\v1.0\\Modules\\', 'PUBLIC': 'C:\\Users\\Public', 'PYCHARM_HOSTED': '1', 'PYTHONIOENCODING': 'UTF-8', 'PYTHONPATH': 'C:\\Users\\Administrator\\PycharmProjects\\s9\\restdemo', 'PYTHONUNBUFFERED': '1', 'SESSIONNAME': 'Console', 'SYSTEMDRIVE': 'C:', 'SYSTEMROOT': 'C:\\Windows', 'TEMP': 'C:\\Users\\ADMINI~1\\AppData\\Local\\Temp', 'TMP': 'C:\\Users\\ADMINI~1\\AppData\\Local\\Temp', 'USERDOMAIN': 'PC201712041709', 'USERNAME': 'Administrator', 'USERPROFILE': 'C:\\Users\\Administrator', 'WINDIR': 'C:\\Windows', 'WINDOWS_TRACING_FLAGS': '3', 'WINDOWS_TRACING_LOGFILE': 'C:\\BVTBin\\Tests\\installpackage\\csilogfile.log', 'RUN_MAIN': 'true', 'SERVER_NAME': 'PC201712041709', 'GATEWAY_INTERFACE': 'CGI/1.1', 'SERVER_PORT': '8000', 'REMOTE_HOST': '', 'CONTENT_LENGTH': '', 'SCRIPT_NAME': '', 'SERVER_PROTOCOL': 'HTTP/1.1', 'SERVER_SOFTWARE': 'WSGIServer/0.2', 'REQUEST_METHOD': 'GET', 'PATH_INFO': '/authors/', 'QUERY_STRING': 'token=8204b8e3ac40bf59ae480d17c146b51a', 'REMOTE_ADDR': '127.0.0.1', 'CONTENT_TYPE': 'text/plain', 'HTTP_HOST': '127.0.0.1:8000', 'HTTP_CONNECTION': 'keep-alive', 'HTTP_USER_AGENT': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36', 'HTTP_UPGRADE_INSECURE_REQUESTS': '1', 'HTTP_ACCEPT': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8', 'HTTP_ACCEPT_ENCODING': 'gzip, deflate, br', 'HTTP_ACCEPT_LANGUAGE': 'zh-CN,zh;q=0.9', 'HTTP_COOKIE': 'csrftoken=jtus3l4GJEc9TFXWYCWxkBIZprcOv7C1vFMIyOHs7Zkxt015FwVZ2KEEeDV6LOyN', 'wsgi.input': <_io.BufferedReader name=832>, 'wsgi.errors': <_io.TextIOWrapper name='<stderr>' mode='w' encoding='UTF-8'>, 'wsgi.version': (1, 0), 'wsgi.run_once': False, 'wsgi.url_scheme': 'http', 'wsgi.multithread': True, 'wsgi.multiprocess': False, 'wsgi.file_wrapper': <class 'wsgiref.util.FileWrapper'>} 7 解析器-----数据解析器 from rest_framework.parsers import JSONParser,FormParser,MultiPartParser,FileUploadParser parser_classes = [JSONParser,FormParser] 8 路由控制 针对: url(r'^authors/$', views.AuthorModelView.as_view({"get":"list","post":"create"}),name="author"), url(r'^authors/(?P<pk>\d+)/$', views.AuthorModelView.as_view({"get":"retrieve","put":"update","delete":"destroy"}),name="detailauthor"), class AuthorModelView(viewsets.ModelViewSet): queryset = Author.objects.all() serializer_class = AuthorModelSerializers url(r'^books/$', views.BookModelView.as_view({"get":"list","post":"create"}),name="author"), url(r'^books/(?P<pk>\d+)/$', views.BookModelView.as_view({"get":"retrieve","put":"update","delete":"destroy"}),name="detailbook"), class AuthorModelView(viewsets.ModelViewSet): queryset = Author.objects.all() serializer_class = AuthorModelSerializers 9 分页 10 响应器 Response
REST_FRAMEWORK = { # 'DEFAULT_AUTHENTICATION_CLASSES': ['app01.utils.TokenAuth'], # 'DEFAULT_PERMISSION_CLASSES': ['app01.utils.SVIPPermission'], # 'DEFAULT_THROTTLE_CLASSES': ['app01.utils.VisitThrottle'], # "DEFAULT_THROTTLE_RATES": { # "visit_rate": "1/m", # } # "PAGE_SIZE":2 }
from django.conf.urls import url,include from django.contrib import admin from app01 import views from rest_framework import routers routers = routers.DefaultRouter() routers.register("authors",views.AuthorModelView) urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^publishes/$', views.PublishView.as_view(), name="publish"), url(r'^publishes/(?P<pk>\d+)/$', views.PublishDetailView.as_view(), name="detail_publish"), url(r"^books/$", views.BookView.as_view(), name="books"), url(r'^books/(?P<pk>\d+)/$', views.BookDetailView.as_view(), name="detail_book"), # url(r'^authors/$',views.AuthorView.as_view(),name="author"), # url(r'^authors/(?P<pk>\d+)',views.AuthorDetailView.as_view(),name="detail_author"), # url(r'^authors/$', views.AuthorModelView.as_view({"get": "list", "post": "create"}), name="author"), # url(r'^authors/(?P<pk>\d+)', # views.AuthorModelView.as_view({"get": "retrieve", "put": "update", "delete": "destroy"}), name="detail_author"), url(r'',include(routers.urls)), url(r'^login/$', views.LoginView.as_view(), name="login") ]
from .models import * from rest_framework import exceptions from rest_framework.authentication import BaseAuthentication class TokenAuth(BaseAuthentication): def authenticate(self,request): token = request.GET.get("token") token_obj = Token.objects.filter(token=token).first() if not token_obj: raise exceptions.AuthenticationFailed("验证失败") return (token_obj.user.name, token_obj) class SVIPPermission(object): message = "只有超级用户才能访问" def has_permission(self,request,view): username = request.user user_type = User.objects.filter(name=username).first().user_type if user_type == 3: return True else: return False # from rest_framework.throttling import BaseThrottle # # VISIT_RECORD={} # class VisitThrottle(BaseThrottle): # # def __init__(self): # self.history=None # # def allow_request(self,request,view): # remote_addr = request.META.get('REMOTE_ADDR') # print(remote_addr) # import time # 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 # else: # return False # # def wait(self): # import time # ctime=time.time() # return 60-(ctime-self.history[-1]) from rest_framework.throttling import SimpleRateThrottle class VisitThrottle(SimpleRateThrottle): scope="visit_rate" def get_cache_key(self, request, view): return self.get_ident(request)
from django.shortcuts import render, HttpResponse from django.views import View from .models import * import json from rest_framework import serializers from rest_framework.views import APIView from rest_framework.response import Response # 为queryset,model 对象 做序列化得 # class PublishSerializers(serializers.Serializer): # name = serializers.CharField() # email = serializers.CharField() class PublishModelSerializers(serializers.ModelSerializer): class Meta: model = Publish fields = "__all__" class BookModelSerializers(serializers.ModelSerializer): class Meta: model = Book fields = "__all__" # 显示超链接 publish = serializers.HyperlinkedIdentityField( view_name='detailpublish', # 别名 含正则表达式 lookup_field= 'publish_id', lookup_url_kwarg='pk' ) # publish = serializers.CharField(source="publish.pk") # publish = serializers.CharField() # authors = serializers.CharField(source="authors.all") # authors = serializers.SerializerMethodField() # def get_authors(self,obj): # temp = [] # for obj in obj.authors.all(): # temp.append(obj.name) # return temp # def create(self, validated_data): # print('--->',validated_data) # book = Book.objects.create(title=validated_data["title"],price=validated_data['price'], # pub_date=validated_data['pub_date'],publish_id=validated_data['publish']['pk']) # book.authors.add(*validated_data['authors']) # # return book class AuthorModelSerializers(serializers.ModelSerializer): class Meta: model = Author fields = "__all__"
from django.db import models # Create your models here. class User(models.Model): name = models.CharField(max_length=32) pwd = models.CharField(max_length=32) type_choices = ((1,"普通用户"),(2,"VIP"),(3,"SVIP")) user_type = models.IntegerField(choices=type_choices,default=1) class Token(models.Model): user = models.OneToOneField("User") token = models.CharField(max_length=128) def __str__(self): return self.token class Book(models.Model): title = models.CharField(max_length=32) price = models.IntegerField() pub_date = models.DateField() publish = models.ForeignKey("Publish") authors = models.ManyToManyField("Author") def __str__(self): return self.title class Publish(models.Model): name = models.CharField(max_length=32) email = models.EmailField() def __str__(self): return self.name class Author(models.Model): name = models.CharField(max_length=32) age = models.IntegerField() def __str__(self): return self.name
from django.shortcuts import render,HttpResponse # Create your views here. from django.views import View from .models import * import json from rest_framework import serializers from rest_framework.views import APIView from rest_framework.response import Response from app01.serializer import * class PublishView(APIView): def get(self, request): publish_list = Publish.objects.all() ret = PublishModelSerializers(publish_list, many=True) return Response(ret.data) def post(self, request): ps = PublishModelSerializers(data=request.data) if ps.is_valid(): ps.save() return Response(ps.data) else: return Response(ps.errors) class PublishDetailView(APIView): def get(self, request, pk): publish = Publish.objects.filter(pk=pk).first() ps = PublishModelSerializers(publish) return Response(ps.data) def put(self, request, pk): publish = Publish.objects.filter(pk=pk).first() ps = PublishModelSerializers(publish, data=request.data) if ps.is_valid(): ps.save() return Response(ps.data) else: return Response(ps.errors) def delete(self, request, pk): Publish.objects.filter(pk=pk).delete() return Response() from rest_framework.parsers import JSONParser,FormParser,MultiPartParser,FileUploadParser """ 默认得是 JSONParser FormParser MultiPartParser """ # Book from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination class MyPageNumberPagination(PageNumberPagination): page_size = 1 page_query_param = "page" page_size_query_param = "size" max_page_size = 2 # 限制 size 得大小 不能超过多少!! # # http://127.0.0.1:8000/books/?page=2&size=2 class MyLimitOffsetPagination(LimitOffsetPagination): default_limit = 1 # limit_query_param = # http://127.0.0.1:8000/books/?limit=2&offset=2 # 偏移 class BookView(APIView): # authentication_classes = [TokenAuth] parser_classes = [JSONParser,FormParser] def get(self,request): print("user:--->", request.user) print(request.auth) book_list = Book.objects.all() # 分页 page_size 配置 setting 全局得 单独怎么设置? 写个类 # from rest_framework.pagination import PageNumberPagination # pnp = PageNumberPagination() # pnp = MyPageNumberPagination() pnp = MyLimitOffsetPagination() books_page = pnp.paginate_queryset(book_list,request,self) # bs = BookModelSerializers(book_list,many=True,context={'request': request}) bs = BookModelSerializers(books_page,many=True,context={'request': request}) # return HttpResponse(bs.data) return Response(bs.data) def post(self,request): print('data:--->', request.data,type(request.data)) # post 请求的数据 bs = BookModelSerializers(data=request.data,context={'request': request}) if bs.is_valid(): bs.save() # create 方法 print(bs.validated_data) return Response(bs.data) else: return Response(bs.errors) class BookDetailView(APIView): def get(self,request,id): book = Book.objects.filter(pk=id).first() # 序列化 bs = BookModelSerializers(book) return Response(bs.data) def put(self,request,id): book = Book.objects.filter(pk=id).first() bs = BookModelSerializers(book,data=request.data) if bs.is_valid(): bs.save() return Response(bs.data) else: return Response(bs.errors) def delete(self,request,id): Book.objects.filter(pk=id).delete() return Response() # Author # 逻辑复用 # 三种方法 ######################### mixin类编写视图 ############################## # from rest_framework import mixins, generics # # class AuthorView(mixins.ListModelMixin,mixins.CreateModelMixin,generics.GenericAPIView): # queryset = Author.objects.all() # serializer_class = AuthorModelSerializers # # def get(self,request,*args,**kwargs): # return self.list(request,*args,**kwargs) # # def post(self,request,*args,**kwargs): # return self.create(self, request, *args, **kwargs) # # # class AuthorDetailView(mixins.RetrieveModelMixin,mixins.DestroyModelMixin,mixins.UpdateModelMixin,generics.GenericAPIView): # queryset = Author.objects.all() # serializer_class = AuthorModelSerializers # # def get(self,request,pk,*args,**kwargs): # return self.retrieve(request,pk,*args,**kwargs) # # def delete(self,request,*args,**kwargs): # return self.destroy(request,*args,**kwargs) # # def put(self,request,*args,**kwargs): # return self.update(request,*args,**kwargs) ######################### 使用得通用得基于类得视图 ############################## # from rest_framework import mixins, generics # # class AuthorView(generics.ListCreateAPIView): # queryset = Author.objects.all() # serializer_class = AuthorModelSerializers # # # class AuthorDetailView(generics.RetrieveUpdateDestroyAPIView): # queryset = Author.objects.all() # serializer_class = AuthorModelSerializers ######################### viewsets.ModelViewSet ############################## # url 需要是一趟线 走一个视图类 # url 中 利用参数 来指定 什么方式 用什么方法 执行 from .utils import TokenAuth,SVIPPermission from rest_framework import viewsets class VisitRateThrottle(object): def allow_request(self,request,view): # 要求访问站点得频率不能超过每分钟20次 if 1: # 每次来 存下来 比对一下,间隔多久 超过一分钟 # IP, 请求首行(request.method request.path) # 请求头(request.meta) 请求体(request.body) print("meta:----->",request.META) print(request.META.get("REMOTE_ADDR")) # 客户端得ip 这里面 你要保存什么 ip 时间 记录下来; # 频率 限制 实现 功能!!! return True else: return False from rest_framework.response import Response class AuthorModelView(viewsets.ModelViewSet): # authentication_classes = [TokenAuth,] # permission_classes = [SVIPPermission,] 取配全局八 # throttle_classes = [VisitRateThrottle] queryset = Author.objects.all() serializer_class = AuthorModelSerializers pagination_class = MyPageNumberPagination # 完美! ok # 类得继承 , 表示形式 需求 展示 数据 ,覆盖方法 单独写 类得继承 可重写 覆盖 # # def list(self,request,*args,**kwargs): # pass # ------------------------------------------------------ def get_random_str(user): import hashlib,time ctime=str(time.time()) md5=hashlib.md5(bytes(user,encoding="utf8")) md5.update(bytes(ctime,encoding="utf8")) return md5.hexdigest() class LoginView(APIView): authentication_classes = [] def post(self,request): name = request.data.get("name") pwd = request.data.get("pwd") user = User.objects.filter(name=name,pwd=pwd).first() res = {"state_code":1000,"msg":None} if user: random_str = get_random_str(user.name) token = Token.objects.update_or_create(user=user,defaults={"token":random_str}) res['token'] = random_str else: res["status_code"] = 1001 # 错误状态码 res['msg'] = "用户名或密码错误" import json return Response(json.dumps(res,ensure_ascii=False))
八、渲染器、版本
配置:
1.添加配置
REST_FRAMEWORK = { 'DEFAULT_RENDERER_CLASSES':['rest_framework.renderers.JSONRenderer','rest_framework.renderers.BrowsableAPIRenderer'], 'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.URLPathVersioning', 'ALLOWED_VERSIONS': ['v1', 'v2'], # 允许的版本 'VERSION_PARAM': 'version', # 参数 'DEFAULT_VERSION': 'v1', # 默认版本 }
2.设置路由:
luffycity/urls.py
from django.conf.urls import url,include from django.contrib import admin urlpatterns = [ # url(r'^admin/', admin.site.urls), url(r'^api/(?P<version>\w+)/', include('api.urls')), ]
api/urls.py
from django.conf.urls import url from api.views import course urlpatterns = [ url(r'^course/$', course.CourseView.as_view()), ]
3.获取版本
request.version 获取版本