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
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)
上面能做的知识单纯的将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"), ]