博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Django REST framework 基本组件
阅读量:5350 次
发布时间:2019-06-15

本文共 14343 字,大约阅读时间需要 47 分钟。

一、序列化组件

简单使用

开发我们的Web API的第一件事是为我们的Web API提供一种将代码片段实例序列化和反序列化为诸如json之类的表示形式的方式。我们可以通过声明与Django forms非常相似的序列化器(serializers)来实现。

models部分:

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.titleclass Publish(models.Model):    name=models.CharField(max_length=32)    email=models.EmailField()    def __str__(self):        return self.nameclass Author(models.Model):    name=models.CharField(max_length=32)    age=models.IntegerField()    def __str__(self):        return self.name

views部分:

from rest_framework.views import APIViewfrom rest_framework.response import Responsefrom .models import *from django.shortcuts import HttpResponsefrom django.core import serializersfrom rest_framework import serializersclass BookSerializers(serializers.Serializer):    title=serializers.CharField(max_length=32)    price=serializers.IntegerField()    pub_date=serializers.DateField()    publish=serializers.CharField(source="publish.name")    #authors=serializers.CharField(source="authors.all")    authors=serializers.SerializerMethodField()    def get_authors(self,obj):        temp=[]        for author in obj.authors.all():            temp.append(author.name)        return tempclass BookViewSet(APIView):    def get(self,request,*args,**kwargs):        book_list=Book.objects.all()        # 序列化方式1:        # from django.forms.models import model_to_dict        # import json        # data=[]        # for obj in book_list:        #     data.append(model_to_dict(obj))        # print(data)        # return HttpResponse("ok")        # 序列化方式2:        # data=serializers.serialize("json",book_list)        # return HttpResponse(data)        # 序列化方式3:        bs=BookSerializers(book_list,many=True)        return Response(bs.data)

ModelSerializer

class BookSerializers(serializers.ModelSerializer):      class Meta:          model=Book          fields="__all__"          depth=1

提交post请求

def post(self,request,*args,**kwargs):               bs=BookSerializers(data=request.data,many=False)        if bs.is_valid():            # print(bs.validated_data)            bs.save()            return Response(bs.data)        else:            return HttpResponse(bs.errors)

重写save中的create方法

class BookSerializers(serializers.ModelSerializer):      class Meta:          model=Book          fields="__all__"          # exclude = ['authors',]          # depth=1      def create(self, validated_data):                  authors = validated_data.pop('authors')          obj = Book.objects.create(**validated_data)          obj.authors.add(*authors)          return obj

单条数据的get和put请求

class BookDetailViewSet(APIView):    def get(self,request,pk):        book_obj=Book.objects.filter(pk=pk).first()        bs=BookSerializers(book_obj)        return Response(bs.data)    def put(self,request,pk):        book_obj=Book.objects.filter(pk=pk).first()        bs=BookSerializers(book_obj,data=request.data)        if bs.is_valid():            bs.save()            return Response(bs.data)        else:            return HttpResponse(bs.errors)

超链接API:Hyperlinked

class BookSerializers(serializers.ModelSerializer):      publish= serializers.HyperlinkedIdentityField(                     view_name='publish_detail',                     lookup_field="publish_id",                     lookup_url_kwarg="pk")      class Meta:          model=Book          fields="__all__"          #depth=1

urls部分:

`urlpatterns ``=` `[``    ``url(r``'^books/$'``, views.BookViewSet.as_view(),name``=``"book_list"``),``    ``url(r``'^books/(?P
\d+)$'``, views.BookDetailViewSet.as_view(),name``=``"book_detail"``),`` ``url(r``'^publishers/$'``, views.PublishViewSet.as_view(),name``=``"publish_list"``),`` ``url(r``'^publishers/(?P
\d+)$'``, views.PublishDetailViewSet.as_view(),name``=``"publish_detail"``),``]`

二、视图组件之视图三部曲

使用混合(mixins)

上一节的视图部分:

from rest_framework.views import APIViewfrom rest_framework.response import Responsefrom .models import *from django.shortcuts import HttpResponsefrom django.core import serializersfrom rest_framework import serializersclass BookSerializers(serializers.ModelSerializer):      class Meta:          model=Book          fields="__all__"          #depth=1class PublshSerializers(serializers.ModelSerializer):      class Meta:          model=Publish          fields="__all__"          depth=1class BookViewSet(APIView):    def get(self,request,*args,**kwargs):        book_list=Book.objects.all()        bs=BookSerializers(book_list,many=True,context={'request': request})        return Response(bs.data)    def post(self,request,*args,**kwargs):        print(request.data)        bs=BookSerializers(data=request.data,many=False)        if bs.is_valid():            print(bs.validated_data)            bs.save()            return Response(bs.data)        else:            return HttpResponse(bs.errors)class BookDetailViewSet(APIView):    def get(self,request,pk):        book_obj=Book.objects.filter(pk=pk).first()        bs=BookSerializers(book_obj,context={'request': request})        return Response(bs.data)    def put(self,request,pk):        book_obj=Book.objects.filter(pk=pk).first()        bs=BookSerializers(book_obj,data=request.data,context={'request': request})        if bs.is_valid():            bs.save()            return Response(bs.data)        else:            return HttpResponse(bs.errors)class PublishViewSet(APIView):    def get(self,request,*args,**kwargs):        publish_list=Publish.objects.all()        bs=PublshSerializers(publish_list,many=True,context={'request': request})        return Response(bs.data)    def post(self,request,*args,**kwargs):        bs=PublshSerializers(data=request.data,many=False)        if bs.is_valid():            # print(bs.validated_data)            bs.save()            return Response(bs.data)        else:            return HttpResponse(bs.errors)class PublishDetailViewSet(APIView):    def get(self,request,pk):        publish_obj=Publish.objects.filter(pk=pk).first()        bs=PublshSerializers(publish_obj,context={'request': request})        return Response(bs.data)    def put(self,request,pk):        publish_obj=Publish.objects.filter(pk=pk).first()        bs=PublshSerializers(publish_obj,data=request.data,context={'request': request})        if bs.is_valid():            bs.save()            return Response(bs.data)        else:            return HttpResponse(bs.errors)

mixin类编写视图

from rest_framework import mixinsfrom rest_framework import genericsclass BookViewSet(mixins.ListModelMixin,                  mixins.CreateModelMixin,                  generics.GenericAPIView):    queryset = Book.objects.all()    serializer_class = BookSerializers    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 BookDetailViewSet(mixins.RetrieveModelMixin,                    mixins.UpdateModelMixin,                    mixins.DestroyModelMixin,                    generics.GenericAPIView):    queryset = Book.objects.all()    serializer_class = BookSerializers    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)

使用通用的基于类的视图

通过使用mixin类,我们使用更少的代码重写了这些视图,但我们还可以再进一步。REST框架提供了一组已经混合好(mixed-in)的通用视图,我们可以使用它来简化我们的views.py模块。

from rest_framework import mixinsfrom rest_framework import genericsclass BookViewSet(generics.ListCreateAPIView):    queryset = Book.objects.all()    serializer_class = BookSerializersclass BookDetailViewSet(generics.RetrieveUpdateDestroyAPIView):    queryset = Book.objects.all()    serializer_class = BookSerializersclass PublishViewSet(generics.ListCreateAPIView):    queryset = Publish.objects.all()    serializer_class = PublshSerializersclass PublishDetailViewSet(generics.RetrieveUpdateDestroyAPIView):    queryset = Publish.objects.all()    serializer_class = PublshSerializers

viewsets.ModelViewSet

urls.py:

url(r'^books/$', views.BookViewSet.as_view({"get":"list","post":"create"}),name="book_list"),    url(r'^books/(?P
\d+)$', views.BookViewSet.as_view({ 'get': 'retrieve', 'put': 'update', 'patch': 'partial_update', 'delete': 'destroy' }),name="book_detail"),

views.py:

class BookViewSet(viewsets.ModelViewSet):    queryset = Book.objects.all()    serializer_class = BookSerializers

三、认证组件

局部视图认证

在app01.service.auth.py:

class Authentication(BaseAuthentication):    def authenticate(self,request):        token=request._request.GET.get("token")        token_obj=UserToken.objects.filter(token=token).first()        if not token_obj:            raise exceptions.AuthenticationFailed("验证失败!")        return (token_obj.user,token_obj)

在views.py:

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()from app01.service.auth import *from django.http import JsonResponseclass LoginViewSet(APIView):    authentication_classes = [Authentication,]    def post(self,request,*args,**kwargs):        res={"code":1000,"msg":None}        try:            user=request._request.POST.get("user")            pwd=request._request.POST.get("pwd")            user_obj=UserInfo.objects.filter(user=user,pwd=pwd).first()            print(user,pwd,user_obj)            if not user_obj:                res["code"]=1001                res["msg"]="用户名或者密码错误"            else:                token=get_random_str(user)                UserToken.objects.update_or_create(user=user_obj,defaults={"token":token})                res["token"]=token        except Exception as e:            res["code"]=1002            res["msg"]=e        return JsonResponse(res,json_dumps_params={"ensure_ascii":False})

全局视图认证组件

settings.py配置如下:

`REST_FRAMEWORK``=``{``    ``"DEFAULT_AUTHENTICATION_CLASSES"``:[``"app01.service.auth.Authentication"``,]``}`

四、权限组件

局部视图权限

在app01.service.permissions.py中:

from rest_framework.permissions import BasePermissionclass SVIPPermission(BasePermission):    message="SVIP才能访问!"    def has_permission(self, request, view):        if request.user.user_type==3:            return True        return False

在views.py:

from app01.service.permissions import *class BookViewSet(generics.ListCreateAPIView):    permission_classes = [SVIPPermission,]    queryset = Book.objects.all()    serializer_class = BookSerializers

全局视图权限

settings.py配置如下:

`REST_FRAMEWORK``=``{``    ``"DEFAULT_AUTHENTICATION_CLASSES"``:[``"app01.service.auth.Authentication"``,],``    ``"DEFAULT_PERMISSION_CLASSES"``:[``"app01.service.permissions.SVIPPermission"``,]``}`

五、throttle(访问频率)组件

局部视图throttle

在app01.service.throttles.py中:

from rest_framework.throttling import BaseThrottleVISIT_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]

在views.py中:

from app01.service.throttles import *class BookViewSet(generics.ListCreateAPIView):    throttle_classes = [VisitThrottle,]    queryset = Book.objects.all()    serializer_class = BookSerializers

全局视图throttle

REST_FRAMEWORK={    "DEFAULT_AUTHENTICATION_CLASSES":["app01.service.auth.Authentication",],    "DEFAULT_PERMISSION_CLASSES":["app01.service.permissions.SVIPPermission",],    "DEFAULT_THROTTLE_CLASSES":["app01.service.throttles.VisitThrottle",]}

内置throttle类

在app01.service.throttles.py修改为:

class VisitThrottle(SimpleRateThrottle):    scope="visit_rate"    def get_cache_key(self, request, view):        return self.get_ident(request)

settings.py设置:

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",    }}

六、解析器

request类

django的request类和rest-framework的request类的源码解析

局部视图

from rest_framework.parsers import JSONParser,FormParserclass 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',]}

七、分页

简单分页

from rest_framework.pagination import PageNumberPagination,LimitOffsetPaginationclass PNPagination(PageNumberPagination):        page_size = 1        page_query_param = 'page'        page_size_query_param = "size"        max_page_size = 5class BookViewSet(viewsets.ModelViewSet):    queryset = Book.objects.all()    serializer_class = BookSerializers    def list(self,request,*args,**kwargs):        book_list=Book.objects.all()        pp=LimitOffsetPagination()        pager_books=pp.paginate_queryset(queryset=book_list,request=request,view=self)        print(pager_books)        bs=BookSerializers(pager_books,many=True)        #return Response(bs.data)        return pp.get_paginated_response(bs.data)

偏移分页

from rest_framework.pagination import LimitOffsetPagination

详细请见:

转载于:https://www.cnblogs.com/wangyueping/p/11470699.html

你可能感兴趣的文章
一个.NET通用JSON解析/构建类的实现(c#)
查看>>
关于这次软件以及pda终端的培训
查看>>
如何辨别一个程序员的水平高低?是靠发量吗?
查看>>
新手村之循环!循环!循环!
查看>>
线程安全问题
查看>>
linux的子进程调用exec( )系列函数
查看>>
MySQLdb & pymsql
查看>>
zju 2744 回文字符 hdu 1544
查看>>
【luogu P2298 Mzc和男家丁的游戏】 题解
查看>>
前端笔记-bom
查看>>
上海淮海中路上苹果旗舰店门口欲砸一台IMAC电脑维权
查看>>
Google透露Android Market恶意程序扫描服务
查看>>
给mysql数据库字段值拼接前缀或后缀。 concat()函数
查看>>
迷宫问题
查看>>
【FZSZ2017暑假提高组Day9】猜数游戏(number)
查看>>
泛型子类_属性类型_重写方法类型
查看>>
对闭包的理解
查看>>
练习10-1 使用递归函数计算1到n之和(10 分
查看>>
Oracle MySQL yaSSL 不明细节缓冲区溢出漏洞2
查看>>
Code Snippet
查看>>