快速实例
序列化
开篇介绍:
---- 一切皆是资源,操作只是请求方式 ----book表增删改查 /books/ books /books/add/ addbook /books/(\d+)/change/ changebook /books/(\d+)/delete/ delbook ----book表增删改查 /books/ -----get books ----- 返回当前所有数据 /books/ -----post books ----- 返回提交数据 /books/(\d+)-----get bookdetail ----- 返回当前查看的单条数据 /books/(\d+)-----put bookdetail ----- 返回更新数据 /books/(\d+)-----delete bookdetail ----- 返回空 class Books(View): def get(self,request): pass # 查看所有书籍 def post(self,request): pass # 添加书籍 class BooksDetail(View): def get(self,request,id): pass # 查看具体书籍 def put(self,request,id): pass # 更新某本书籍 def delete(self,request,id): pass # 删除某本书籍
创建一个序列化类
简单使用
开发我们的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",on_delete=models.CASCADE) 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 django.shortcuts import render,HttpResponse import json from django.views import View from .models import * from app01.serialize import * from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import serializers #这是rest_framework的序列化组件
#为queryset(需要加many=True),model对象做序列化 class PublishSerializers(serializers.Serializer): name =serializers.CharField() email=serializers.CharField() class PublishView(APIView): def get(self,request): #取数据 print(request.GET) publish_list = Publish.objects.all() #序列化 #方式一: #publish_list=list(Publish.objects.all().values("name","email")) #方式二: # from django.forms.models import model_to_dict # publish_list = Publish.objects.all() # temp=[] # for obj in publish_list: # #利用这方法可以将字段和值对应组合成一个字典,一条数据一个字典。 # temp.append(model_to_dict(obj)) #方式三 # from django.core import serializers # publish_list = Publish.objects.all() # ret=serializers.serialize("json",publish_list) #方式四(restframework序列化) ps=PublishSerializers(publish_list,many=True) return HttpResponse(ps.data)
一对多和多对多字段的序列化:
class BookSerializers(serializers.Serializer): title = serializers.CharField(max_length=32) price = serializers.IntegerField() pub_date = serializers.DateField() publish = serializers.CharField(source="publish.email") # 一对多字段使用source字段处理 # 多对多使用下面字段,并且配一个方法,方法里面可自定义任意东西,可取作者表的名字。 authors = serializers.SerializerMethodField() def get_authors(self, obj): temp = [] for obj in obj.authors.all(): temp.append(obj.name) return temp
序列化的过程:
‘‘‘ 序列化BookSerializers(book_list,many=True)过程: temp=[] for obj in book_list: temp.append({ "title":obj.title, "price":obj.price, "pub_date":obj.pub_date, #"publish":str(publish), "publish":obj.publish.name, "authors":get_authors(obj) }) ‘‘‘
ModelSerializer(类似于ModelForm):
class PublishModelSerializers(serializers.ModelSerializer): class Meta: model = Publish fields = "__all__"
提交post请求:
def post(self,request): #原生request支持的操作 # print(request.POST) # print(request.body) # print(type(request)) from django.core.handlers.wsgi import WSGIRequest #新的request支持的操作 print("request_data",request.data) #request_data {‘name‘: ‘jesi‘, ‘email‘: ‘666@qq.com‘} print("request_data_type",type(request.data)) #request_data_type <class ‘dict‘> return HttpResponse("POST")
get和post:
class BookView(APIView): def get(self,request): book_list=Book.objects.all() # bs=BookSerializers(book_list,many=True) bs2=BookModelSerializers(book_list,many=True,context={‘request‘: request}) # return Response(bs.data) return Response(bs2.data) def post(self,request): #post请求的数据 bs=BookModelSerializers(data=request.data)
#post请求过来的数据如果通过了校验就创建一条数据,如果没有返回错误信息。 if bs.is_valid(): bs.save() return Response(bs.data) else: return Response(bs.errors)
重写save中的create方法:
# ModelSerializers class BookModelSerializers(serializers.ModelSerializer): class Meta: model = Book fields = "__all__" # publish = serializers.CharField(source="publish.pk") # 一对多字段使用source字段处理
# 因为上面自定制了字段,所以这个添加方法需要重写才可以。 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 BookModelSerializers(serializers.ModelSerializer): class Meta: model = Book fields = "__all__" publish = serializers.CharField(source="publish.pk") # 一对多字段使用source字段处理 # # #多对多使用下面字段,并且配一个方法,方法里面可自定义任意东西,可取作者表的名字。 # 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
单条数据的get和put请求:
直接通过序列化的实例对象做一个校验,对传入的ID值对应的书籍进行增删改查。
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,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()
超链接API:Hyperlinked
class BookModelSerializers(serializers.ModelSerializer): class Meta: model = Book fields = "__all__" publish=serializers.HyperlinkedIdentityField( view_name="publishdetail", lookup_field="publish_id", lookup_url_kwarg="id", )
urls部分:
urlpatterns = [ path(‘admin/‘, admin.site.urls), url(r‘publishes/$‘, views.PublishView.as_view(),name="publish"), url(r‘publishes/(?P<id>\d+)/$‘, views.PublishDetailView.as_view(),name="publishdetail"), url(r‘books/$‘, views.BookView.as_view(),name="books"), url(r‘books/(\d+)/$‘, views.BookDetailView.as_view(),name="bookdetail"), ]
这里有一个点需要注意一下:
class BookView(APIView): def get(self,request): book_list=Book.objects.all() # bs=BookSerializers(book_list,many=True) bs2=BookModelSerializers(book_list,many=True,context={‘request‘: request}) # return Response(bs.data) return Response(bs2.data) 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)
最后总结:
总结: 1 reuqest类----源码 2 restframework 下的APIView--源码 url(r‘^books/$‘, views.BookView.as_view(),name="books")# View下的view books/一旦被访问: view(request) ------APIView: dispatch() 3 def dispatch(): 构建request对象 self.request=Request(request) self.request._request self.request.GET # get self.request.data # POST PUT 分发----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 4 序列化类 # from django.core import serializers # ret=serializers.serialize("json",publish_list) restframework下的序列类 BookModelSerializers 将queryset或者model对象序列成一json数据 bs=BookModelSerializers(book_list,many=True,context={‘request‘: request}) bs=BookModelSerializers(book,context={‘request‘: request}) 还可以做校验数据,json-------》queryset/model-->记录 bs=BookModelSerializers(data=request.data) if bs.is_valid(): print(bs.validated_data) bs.save() # 重写create方法 5 操作数据: 以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()
代码:
views.py
from django.shortcuts import render,HttpResponse import json from django.views import View from .models import * from app01.serialize import * from rest_framework.views import APIView from rest_framework.response import Response class PublishView(APIView): def get(self,request): #取数据 print(request.GET) publish_list = Publish.objects.all() #序列化 #方式一: #publish_list=list(Publish.objects.all().values("name","email")) #方式二: # from django.forms.models import model_to_dict # publish_list = Publish.objects.all() # temp=[] # for obj in publish_list: # #利用这方法可以将字段和值对应组合成一个字典,一条数据一个字典。 # temp.append(model_to_dict(obj)) #方式三 # from django.core import serializers # publish_list = Publish.objects.all() # ret=serializers.serialize("json",publish_list) #方式四(restframework序列化) ps=PublishSerializers(publish_list,many=True) return HttpResponse(ps.data) def post(self,request): #原生request支持的操作 # print(request.POST) # print(request.body) # print(type(request)) from django.core.handlers.wsgi import WSGIRequest #新的request支持的操作 print("request_data",request.data) #request_data {‘name‘: ‘jesi‘, ‘email‘: ‘666@qq.com‘} print("request_data_type",type(request.data)) #request_data_type <class ‘dict‘> return HttpResponse("POST") class PublishDetailView(APIView): def get(self,request,id): #单条数据查看 publish=Publish.objects.filter(pk=id).first() ps=PublishModelSerializers(publish) return Response(ps.data) def put(self,request,id): #更新单条数据 publish=Publish.objects.filter(pk=id).first() ps = PublishModelSerializers(publish,request.data) if ps.is_valid(): ps.save() return Response(ps.data) else: return Response(ps.errors) def delete(self,request,id): Publish.objects.filter(pk=id).delete() return Response() class BookView(APIView): def get(self,request): book_list=Book.objects.all() # bs=BookSerializers(book_list,many=True) bs2=BookModelSerializers(book_list,many=True,context={‘request‘: request}) # return Response(bs.data) return Response(bs2.data) def post(self,request): #post请求的数据 bs=BookModelSerializers(data=request.data) if bs.is_valid(): bs.save() 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,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()
serialize.py
# Author:Jesi # Time : 2018/10/5 11:29 from app01.models import * from rest_framework import serializers #这是rest_framework的序列化组件 #为queryset(需要加many=True),model对象做序列化 class PublishSerializers(serializers.Serializer): name =serializers.CharField() email=serializers.CharField() # Serializers class BookSerializers(serializers.Serializer): title = serializers.CharField(max_length=32) price = serializers.IntegerField() pub_date = serializers.DateField() publish = serializers.CharField(source="publish.email") # 一对多字段使用source字段处理 # 多对多使用下面字段,并且配一个方法,方法里面可自定义任意东西,可取作者表的名字。 authors = serializers.SerializerMethodField() def get_authors(self, obj): temp = [] for obj in obj.authors.all(): temp.append(obj.name) return temp ‘‘‘ 序列化BookSerializers(book_list,many=True)过程: temp=[] for obj in book_list: temp.append({ "title":obj.title, "price":obj.price, "pub_date":obj.pub_date, #"publish":str(publish), "publish":obj.publish.name, "authors":get_authors(obj) }) ‘‘‘ class PublishModelSerializers(serializers.ModelSerializer): class Meta: model = Publish fields = "__all__" # ModelSerializers class BookModelSerializers(serializers.ModelSerializer): class Meta: model = Book fields = "__all__" publish=serializers.HyperlinkedIdentityField( view_name="publishdetail", lookup_field="publish_id", lookup_url_kwarg="id", ) # publish = serializers.CharField(source="publish.pk") # 一对多字段使用source字段处理 # # #多对多使用下面字段,并且配一个方法,方法里面可自定义任意东西,可取作者表的名字。 # 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
urls.py
from django.contrib import admin from django.urls import path from django.conf.urls import url from app01 import views urlpatterns = [ path(‘admin/‘, admin.site.urls), url(r‘publishes/$‘, views.PublishView.as_view(),name="publish"), url(r‘publishes/(?P<id>\d+)/$‘, views.PublishDetailView.as_view(),name="publishdetail"), url(r‘books/$‘, views.BookView.as_view(),name="books"), url(r‘books/(\d+)/$‘, views.BookDetailView.as_view(),name="bookdetail"), ]