Django 之restframework1

Restframework

这里先简单的介绍一下restful协议

  ----一切皆是资源,操作只是请求方式


基于restful协议的框架有很多
Django下的restframework只是其中的一种

restful协议是一套开发的规范,url里不能有动作相关的词汇,比如add,edit,这些都通过用请求的方式来实现

以前----book表增删改查
        /books/                    books
        /books/add/                addbook
        /books/(\d+)/change/    change
        /books/(\d+)/delete        delete
        
        
    现在----book表增删改查
        /books/        ---get        books --->返回所有的数据
        /books//        ---post        books    --->返回提交的数据
        
        /books/(\d+)/     ----put        bookdetail    --->返回更新的数据    
        /books/(\d+)/    ----delete    bookdetail  ---->返回空
        有参数不一样的class类
        
        class Books(View):
            def get(self,requset):
                pass #查看所有书籍
                
            def post(self,request):
                pass #添加书籍
                
        class BooksDetail(View):
            def get(self,request,id):
                pass #查看某一本书籍
        
            def put(self,requset,id):
                pass #更新书籍
                
            def delete(self,request,id):
                pass #删除书籍

 

在父类的基础上扩展,并执行父类方法

继承后调用父类的方法:
    扩展后子类继续调用父类的方法:
    class LoginView(View):
        def dispatch(self,request,*arg,**kwargs):
        # 两种方式都可以
                       print('扩展父类方法')
            ret = super(LoginView,self).dispatch(self,request,*arg,**kwargs)
            ret = super().dispatch(self,request,*arg,**kwargs)
            return ret

序列化

创建一个序列化类

开发我们的Web API的第一件事是为我们的Web API提供一种将代码片段实例序列化和反序列化为诸如json之类的表示形式的方式。

 

model类

rom 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
model

 

views部分:

from rest_framework.views import APIView
from rest_framework.response import Response
from .models import *
from django.shortcuts import HttpResponse
from django.core import serializers


from rest_framework import serializers

class 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 temp


class 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)
View Code

 

 

上面能做的知识单纯的将queryset序列化,那么有没有能够既能够序列化对象传给前端,

又能够接受前端的数据然后更新到数据库呢?

ModelSerializer

modelserializer和modelform很类似,用法也很相似.

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 Response(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 Response(bs.errors)

 

我们可以看到中间CBV的类继承了restframework的APIView,那么里面的继承关系,和流程是怎么样的呢?

url(r'^books/$', views.BookView.as_view(),name="books")# View下的view

books/一旦被访问: view(request) ------APIView: dispatch()

在restframework的dispatch方法里干了什么事?

重新构建request对象
self.request=Request(request)
self.request._request

分发----if get请求:
if request.method.lower() in self.http_method_names:
handler = getattr(self, request.method.lower(),
self.http_method_not_allowed)
else:
handler = self.http_method_not_allowed

response = handler(request, *args, **kwargs) # self.get(request, *args, **kwargs)

return response

 

 

流程图:

 

 

 

Django原生的request:

 

如何在重构的request对象里获取数据?

request.GET  # get

request.data # POST  PUT delete

 

 

超链接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<pk>\d+)$', views.BookDetailViewSet.as_view(),name="book_detail"),
    url(r'^publishers/$', views.PublishViewSet.as_view(),name="publish_list"),
    url(r'^publishers/(?P<pk>\d+)$', views.PublishDetailViewSet.as_view(),name="publish_detail"),
]

 

参考这里

 

posted @ 2018-07-19 20:32  R00M  阅读(319)  评论(0编辑  收藏  举报