rest_framework2 APIView与序列化组件
1、入门

1.1 参考blog
官方文档:http://www.django-rest-framework.org/tutorial/quickstart/#quickstart
yuan的Blog:http://www.cnblogs.com/yuanchenqi/articles/8719520.html
alice的Blog:https://www.cnblogs.com/alice-bj/p/9228402.html
1.2 restful协议
restful协议
---- 一切皆是资源,操作只是请求方式
----book表增删改查
/books/ books
/books/add/ addbook
/books/(\d+)/change/ changebook
/books/(\d+)/delete/ delbook
----book表增删改查 url里面不能出现动词!!
/books/ -----get books ----- 返回当前所有数据
/books/ -----post books ----- 返回提交数据
/books/(\d+)-----get bookdetail ----- 返回当前查看的单条数据
/books/(\d+)-----put bookdetail ----- 返回更新数据
/books/(\d+)-----delete bookdetail ----- 返回空
1.3 安装
pip install django
pip install djangorestframework
2. 序列化方法
序列化是什么? QuerySet-->list-->json
2.1 restdemo
model
from django.db import models
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
url
from django.contrib import admin
from django.urls import path
from app01 import views
urlpatterns = [
path('admin/', admin.site.urls),
path('publishes/', views.PublishView.as_view()),
]
view
from django.shortcuts import render,HttpResponse
# Create your views here.
from django.views import View
from .models import Publish
import json
class PublishView(View):
def get(self,request):
# QuerySet-->vales取值--->list--->json
publish_list = list(Publish.objects.all().values("name","email"))
return HttpResponse(json.dumps(publish_list))
def post(self,request):
pass
database

data生成与迁移
python manage.py makemigrations
python manage.py migrate
运行django项目

2.2 方式1 :list()

2.3 方式2:model_to_dict(obj)


2.4 方式3:django serializers


2.5 方式4 :restframework serializers (推荐)


2.6 code
from django.shortcuts import render,HttpResponse
# 为queryset,model对象做序列化
from rest_framework import serializers # rest_framework的序列化组件
class PublishSerializers(serializers.Serializer):
# 对哪些字段序列化
name = serializers.CharField()
email = serializers.EmailField()
from django.views import View
from .models import Publish
import json
class PublishView(View):
def get(self,request):
# QuerySet--->list--->json
# 序列化方式1 # list()
# publish_list = list(Publish.objects.all().values("name","email"))
#return HttpResponse(json.dumps(publish_list))
# 序列化方式2 # model对象转换为dict
# 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))
#
# # temp.append({
# # "name":obj.name,
# # "email":obj.email
# # })
#
# return HttpResponse(temp)
#
# 序列化方式3 # django的序列化组件
# from django.core import serializers
# publish_list = Publish.objects.all()
# ret = serializers.serialize("json",publish_list)
#
# return HttpResponse(ret)
# 序列化方式4 rest_framework的序列化组件
publish_list = Publish.objects.all()
ret = PublishSerializers(publish_list,many=True)
return HttpResponse(ret.data)
def post(self,request):
pass
3.取数据:APIView
3.1 Django的原生request
1.get取数据



2.post取数据



3. request实质就是http报文头
(1)Django的原生request:
浏览器 ------------- 服务器
"GET url?a=1&b=2 http/1.1\r\user_agent:Google\r\ncontentType:urlencoded\r\n\r\n"
"POST url http/1.1\r\user_agent:Google\r\ncontentType:urlencoded\r\n\r\na=1&b=2"
request.body: a=1&b=2
request.POST:
if contentType:urlencoded:
a=1&b=2----->{"a":1,"b":2}
4.发送json


3.2 原生request源码
content-type



3.3 restframework下的 APIView

1. 新的request 取数据


2. urlencoded类型的data


3. get请求



3.3 APIView源码
1. 继承了基本的View



2. APIView下的dispatch



3.4 view代码
get:
request._request ( 原request )
request.GET == request._request.GET
post:
request.data ( 得到 json 数据,也可得到 urlencode 数据)
都是 rest_framework APIView 的功劳,
如果使用 View , request.post( 只能得到 urlencode 的数据,不能得到 json 数据,只能从 request.body 中取)
from django.shortcuts import render,HttpResponse
from django.views import View
from rest_framework.views import APIView
# class PublishView(View): # 原生View
class PublishView(APIView): # APIView
def get(self,request):
# 取数据
print("request.data ",request.data)
print("request.data type ",type(request.data))
print(request._request.GET) #旧的request
print(request.GET)
return HttpResponse("123")
def post(self,request):
# 取数据
# 1 原生reqeust支持的操作
# print("post...",request.POST)
# print("body...",request.body)
# print(type(request)) # <class 'django.core.handlers.wsgi.WSGIRequest'>
# from django.core.handlers.wsgi import WSGIRequest
# 2 新的reqeust支持的操作
# request._request.POST # 取出旧的request
print("request.data ",request.data)
print("request.data type ",type(request.data))
return HttpResponse("POST")
4. 序列化字段:Serializer
4.1 准备demo
1. views
from django.shortcuts import render,HttpResponse
# 为queryset,model对象做序列化
from rest_framework import serializers # rest_framework的序列化组件
class PublishSerializers(serializers.Serializer):
# 对哪些字段序列化
name = serializers.CharField()
email = serializers.EmailField()
# 为Book做序列化
class BookSerializers(serializers.Serializer):
title = serializers.CharField(max_length=32)
price = serializers.IntegerField()
pub_date = serializers.DateField()
from rest_framework.views import APIView
class PublishView(APIView): # APIView
def get(self,request):
return HttpResponse("123")
def post(self,request):
return HttpResponse("POST")
from .models import Book
class BookView(APIView):
def get(self,request):
book_list = Book.objects.all()
bs = BookSerializers(book_list,many=True)
return HttpResponse(bs.data)
def post(self,request):
pass
2. database

Question报错:
return datetime.date(*map(int, val.split(b"-")))
OverflowError: Python int too large to convert to C long

原因:估计是sqlite中datetime的问题

解决办法:创建superuser,进入admin页面,添加书籍,生成到数据库的data

4.2 响应器 response
""" 响应器
针对 不同得访问者 浏览器 postman 做不同得处理
只有浏览器,用户 会给一个页面!!
几种请求方式
get post
get put delete
"""
1.Response继承了HttpResponse


2. restframework就是一个app,需要注册

3.get得到的data实质

4.3 默认打印__str__定制的字段

# publish = serializers.CharField() # 默认打印 __str__定义的字段名
publish = serializers.CharField(source="publish.name")
5. 如何一对多显示

# 一对多
# authors = serializers.CharField(source="authors.all") #"authors": "<QuerySet [<Author: alex>, <Author: yuan>]>"
authors = serializers.SerializerMethodField()
def get_authors(self,obj):
temp = []
for obj in obj.authors.all():
temp.append(obj.name)
return temp
4.4 序列化的过程
"""
序列化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(obj.publish), # obj.publish.name
"authors":get_authors(obj)
})
return HttpResponse(temp)
"""
4.5 code代码
view
from django.shortcuts import render,HttpResponse
# 为queryset,model对象做序列化
from rest_framework import serializers # rest_framework的序列化组件
class PublishSerializers(serializers.Serializer):
# 对哪些字段序列化
name = serializers.CharField()
email = serializers.EmailField()
# 为Book做序列化
class BookSerializers(serializers.Serializer):
title = serializers.CharField(max_length=32)
price = serializers.IntegerField()
pub_date = serializers.DateField()
# publish = serializers.CharField() # 默认打印 __str__定义的字段名
publish = serializers.CharField(source="publish.name")
# 一对多
# authors = serializers.CharField(source="authors.all") #"authors": "<QuerySet [<Author: alex>, <Author: yuan>]>"
authors = serializers.SerializerMethodField()
def get_authors(self,obj):
temp = []
for obj in obj.authors.all():
temp.append(obj.name)
return temp
from rest_framework.views import APIView
class PublishView(APIView): # APIView
def get(self,request):
return HttpResponse("123")
def post(self,request):
return HttpResponse("POST")
from .models import Book
from rest_framework.response import Response
class BookView(APIView):
def get(self,request):
book_list = Book.objects.all()
bs = BookSerializers(book_list,many=True)
# return HttpResponse(bs.data)
return Response(bs.data) # Response继承HttpResponse
def post(self,request):
pass
5.序列化模型:ModelSerializers
5.1 以Book为例
from django.shortcuts import render,HttpResponse
from .models import Book
from rest_framework import serializers # rest_framework的序列化组件
from rest_framework.views import APIView
from rest_framework.response import Response
class BookModelSerializers(serializers.ModelSerializer): # ModelSerializer
class Meta:
model = Book
fields = '__all__'
class BookView(APIView):
def get(self,request):
book_list = Book.objects.all()
bs = BookModelSerializers(book_list,many=True)
return Response(bs.data) # Response继承HttpResponse
def post(self,request):
pass
class PublishSerializers(serializers.Serializer):
# 对哪些字段序列化
name = serializers.CharField()
email = serializers.EmailField()
class PublishView(APIView): # APIView
def get(self,request):
return HttpResponse("123")
def post(self,request):
return HttpResponse("POST")


5.2 get请求:显示书籍,自定制
自定制字段的source

# 如何显示字段
publish = serializers.CharField(source="publish.name") # 原生的create不接受自定制,需要重写create方法
authors = serializers.SerializerMethodField(source="authors.all")
def get_authors(self,obj):
temp = []
for obj in obj.authors.all():
temp.append(obj.name)
return temp
5.3 post请求,保存书籍
1. 取消自定制的,source
create方法中没有source自定义

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)
2. 源码create

3. 发送json数据,提交到database


5.4 重写create方法
原生的create不接受自定制,需要重写create方法



class BookModelSerializers(serializers.ModelSerializer): # ModelSerializer
class Meta:
model = Book
fields = '__all__'
# 如何显示字段
publish = serializers.CharField(source="publish.name") # 原生的create不接受自定制,需要重写create方法
# 重写create方法 # 不接受自定制字段,source
def create(self, validated_data):
print("validated_data...",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']['name'])
book.authors.add(*validated_data['authors'])
return book
6.单条数据(get,put,delete)
6.1 解耦:新建serializer.py

1.serializer.py
from rest_framework import serializers # rest_framework的序列化组件
from .models import Book
class PublishSerializers(serializers.Serializer):
name = serializers.CharField()
email = serializers.EmailField()
class BookModelSerializers(serializers.ModelSerializer): # ModelSerializer
class Meta:
model = Book
fields = '__all__'
2. view.py
from django.shortcuts import render,HttpResponse
from rest_framework.views import APIView
from rest_framework.response import Response
from app01.serilizer import BookModelSerializers # 从serilizer中导入
from .models import Book
class PublishView(APIView): # APIView
def get(self,request):
return HttpResponse("123")
def post(self,request):
return HttpResponse("POST")
class BookView(APIView):
def get(self,request):
book_list = Book.objects.all()
bs = BookModelSerializers(book_list,many=True)
return Response(bs.data) # Response继承HttpResponse
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)
6.2 单条数据demo
urls:正则表达式用re_path
from django.contrib import admin
from django.urls import path
from django.urls import re_path # 正则表达式的
from app01 import views
urlpatterns = [
path('admin/', admin.site.urls),
path('publishes/', views.PublishView.as_view()), # view(request)====> APIView:dispatch()
path('books/', views.BookView.as_view()),
re_path(r'books/(\d+)/$', views.BookDetailView.as_view()),
]
view
from django.shortcuts import render,HttpResponse
from rest_framework.views import APIView
from rest_framework.response import Response
from app01.serilizer import BookModelSerializers # 从serilizer中导入
from .models import Book
class PublishView(APIView): # APIView
def get(self,request):
return HttpResponse("123")
def post(self,request):
return HttpResponse("POST")
class BookView(APIView):
def get(self,request):
book_list = Book.objects.all()
bs = BookModelSerializers(book_list,many=True)
return Response(bs.data) # Response继承HttpResponse
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() # 过滤单挑data
bs = BookModelSerializers(book)
return Response(bs.data)
def put(self,rquest,id):
# 更新某本书的字段
book = Book.objects.filter(pk=id).first()
bs = BookModelSerializers(book,data=rquest.data)
if bs.is_valid():
bs.save() # 实质create方法
return Response(bs.data)
else:
return Response(bs.errors)
def delete(self,request,id):
# 删除某条数据
Book.objects.filter(pk=id).delete()
return Response("Delete 第%s本书成功"%(id))
get取数据

更新data
{ "title": "野兽绅士","price": 88, "pub_date": "2019-07-23","publish": 2,"authors": [1,2]}



delete

7.超链接API
7.1 配置publish为单条数据
urls
from django.contrib import admin
from django.urls import path
from django.urls import re_path # 正则表达式的
from app01 import views
urlpatterns = [
path('admin/', admin.site.urls),
path('publishes/', views.PublishView.as_view()), # view(request)====> APIView:dispatch()
re_path(r'publishes/(\d+)/$', views.PublishDetailView.as_view()),
path('books/', views.BookView.as_view()),
re_path(r'books/(\d+)/$', views.BookDetailView.as_view()),
]
serilizer
from rest_framework import serializers # rest_framework的序列化组件
from .models import Book,Publish
class PublishSerializers(serializers.Serializer):
name = serializers.CharField()
email = serializers.EmailField()
class BookModelSerializers(serializers.ModelSerializer): # ModelSerializer
class Meta:
model = Book
fields = '__all__'
class PublishModelSerializers(serializers.ModelSerializer): # ModelSerializer
class Meta:
model = Publish
fields = '__all__'
views
from django.shortcuts import render,HttpResponse
from rest_framework.views import APIView
from rest_framework.response import Response
from app01.serilizer import BookModelSerializers # 从serilizer中导入
from app01.serilizer import PublishModelSerializers #
from .models import Book,Publish
class PublishView(APIView): # APIView
def get(self,request):
publish_list = Publish.objects.all()
ps = PublishModelSerializers(publish_list,many=True)
return Response(ps.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,id):
# 获取某publish的信息
publish = Publish.objects.filter(pk=id).first()
ps = PublishModelSerializers(publish)
return Response(ps.data)
def put(self,request,id):
# 更新某pub的信息
publish = Publish.objects.filter(pk=id).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,id):
# 删除某天publish
Publish.objects.filter(pk=id).delete()
return Response("Delete 第%s个出版社"%(id))
class BookView(APIView):
def get(self,request):
book_list = Book.objects.all()
bs = BookModelSerializers(book_list,many=True)
return Response(bs.data) # Response继承HttpResponse
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() # 过滤单挑data
bs = BookModelSerializers(book)
return Response(bs.data)
def put(self,rquest,id):
# 更新某本书的字段
book = Book.objects.filter(pk=id).first()
bs = BookModelSerializers(book,data=rquest.data)
if bs.is_valid():
bs.save() # 实质create方法
return Response(bs.data)
else:
return Response(bs.errors)
def delete(self,request,id):
# 删除某条数据
Book.objects.filter(pk=id).delete()
return Response("Delete 第%s本书成功"%(id))


7.2 配置超链接
1.效果图


2.urls

3.serilizer中,定义超链接

4.view中id修改pk

5. view中调用 Serializers的地方,重新什么request

7.3 code代码
urls
View Code
views
View Code
serilizer
View Code
8. 今日总结
CBV与FBV
restful协议
---- 一切皆是资源,操作只是请求方式
----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 # 删除某本书籍
restframework(Django)
----针对数据:json
(1)Django的原生request:
浏览器 ------------- 服务器
"GET url?a=1&b=2 http/1.1\r\user_agent:Google\r\ncontentType:urlencoded\r\n\r\n"
"POST url http/1.1\r\user_agent:Google\r\ncontentType:urlencoded\r\n\r\na=1&b=2"
request.body: a=1&b=2
request.POST:
if contentType:urlencoded:
a=1&b=2----->{"a":1,"b":2}
(2)restframework 下的APIView:
(3)
class PublishSerializers(serializers.Serializer):
name=serializers.CharField()
email=serializers.CharField()
PublishSerializers(queryset,many=true)
PublishSerializers(model_obj)
总结:
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()
restframework
1 APIView
2 序列组件
3 视图、
4 组件(认证权限频率)
5 数据解析器
6 分页和Response

浙公网安备 33010602011771号