Rest-framework框架的基本组件
快速实例:
序列化类
开发我们的Web API的第一件事是为我们的Web API提供一种将代码片段实例序列化和反序列化为诸如
json
之类的表示形式的方式。我们可以通过声明与Django forms非常相似的序列化器(serializers)来实现。简单实用(基于django原生serializers基于CBV)
models.py
28
1
from django.db import models
2
3
4
class Book(models.Model):
5
title = models.CharField(max_length=32)
6
price = models.IntegerField()
7
pub_date = models.DateField()
8
publish = models.ForeignKey("Publish", on_delete=models.CASCADE)
9
authors = models.ManyToManyField("Author")
10
11
def __str__(self):
12
return self.title
13
14
15
class Publish(models.Model):
16
name = models.CharField(max_length=32)
17
email = models.EmailField()
18
19
def __str__(self):
20
return self.name
21
22
23
class Author(models.Model):
24
name = models.CharField(max_length=32)
25
age = models.IntegerField()
26
27
def __str__(self):
28
return self.name
方式一:
分发url
3
1
...
2
path('publishes/', views.PublishesView.as_view()),
3
...
视图类
41
1
import json
2
from django.shortcuts import render, HttpResponse
3
from django.views import View
4
from django.forms.models import model_to_dict
5
from .models import *
6
7
8
class PublishesView(View):
9
# Publish.objects.all().values("name", "email")
10
# <QuerySet [{'name': '苹果出版社', 'email': '123@qq.com'}, {'name': '橘子出版社', 'email': '234@qq.com'}]>
11
# list(Publish.objects.all().values("name", "email"))
12
# [{'name': '苹果出版社', 'email': '123@qq.com'}, {'name': '橘子出版社', 'email': '234@qq.com'}]
13
def get(self, request):
14
# 序列化方式一
15
# publish_list = list(Publish.objects.all().values("name", "email")) # 注意这个list()
16
# return HttpResponse(json.dumps(publish_list))
17
18
# 序列化方式二
19
# 使用model_to_dict(obj)
20
# publish_list = Publish.objects.all()
21
# temp = []
22
# for obj in publish_list: # 每一个obj就是类对象
23
"""
24
temp.append({
25
"name": "obj.name",
26
"email": "obj.email"
27
})
28
"""
29
# temp.append(model_to_dict(obj))
30
# return HttpResponse(json.dumps(temp))
31
32
# 序列化方式三
33
# publish_list = Publish.objects.all()
34
# from django.core import serializers
35
# ret = serializers.serialize('json', publish_list)
36
# return HttpResponse(ret)
37
38
采用restframework
39
40
def post(self, request):
41
pass
得到数据
model_to_dict(obj) {'id': 1, 'name': '苹果出版社', ‘email’: '123@qq.com'}
使用rest_framework来序列化
20
1
from rest_framework import serializers
2
from rest_framework.response import Response
3
from rest_framework.views import APIView
4
5
6
# 为queryset做序列化
7
class PublishSerializers(serializers.Serializer):
8
"""等同于form.Form"""
9
name = serializers.CharField()
10
email = serializers.CharField()
11
12
13
class PublishesView(APIView):
14
def get(self, request):
15
publish_list = Publish.objects.all()
16
ps = PublishSerializers(publish_list, many=True) # 即可接收Queryset 也可接收 model_obj
17
return Response(ps.data)
18
19
def post(self, request):
20
pass
得到的结果在页面中不会显示,会在postmen中显示
10
1
[
2
{
3
"name": "苹果出版社",
4
"email": "123@qq.com"
5
},
6
{
7
"name": "橘子出版社",
8
"email": "234@qq.com"
9
}
10
]
解析器request类
django的request类和rest-framework的request类的源码解析
依然是上面的代码 用postmen发送一次post请求
10
1
class PublishesView(View):
2
def post(self, request):
3
print("POST", request.POST)
4
print("BODY", request.body)
5
6
return HttpResponse("POST")
7
8
>>>POST <QueryDict: {'a': ['1'], 'b': ['2']}>
9
[18/Oct/2018 16:19:02] "POST /publishes/ HTTP/1.1" 200 4
10
BODY b'a=1&b=2'
这个过程里面到底发生了什么?
这个过程其实就是一次Django的请求周期
2
1
# request 源码的入口
2
from django.core.handlers.wsgi import WSGIRequest
rest_framework下面的APIview
1
1
from rest_framework.views import APIView
OK reas_framework request 请求的取值问题
12
1
from rest_framework.response import Response
2
from rest_framework.views import APIView
3
4
5
class PublishesView(APIView):
6
def post(self, request):
7
# 原生的request支持的操作
8
# print("POST", request.POST)
9
# print("BODY", request.body)
10
11
return Response("POST")
12
27
1
from rest_framework import serializers
2
from rest_framework.response import Response
3
from rest_framework.views import APIView
4
5
6
# 为queryset做序列化
7
class BookSerializers(serializers.Serializer):
8
"""Book表是一个比较复杂的表包含了一对多与多对多"""
9
title = serializers.CharField()
10
price = serializers.IntegerField()
11
pub_date = serializers.DateField()
12
# 这怎么办?
13
# publish = models.ForeignKey("Publish", on_delete=models.CASCADE) # 一对多
14
# authors = models.ManyToManyField("Author") # 多对多
15
publish = serializers.CharField(source="publish.name") # 一对多、类名小写
16
# 多对多的话这个sourse不好使,得到的是Queryset
17
authors = serializers.CharField(source="authors.all") # 多对多、类名小写.all() 自动执行
18
19
20
class BookView(APIView):
21
def get(self, request):
22
book_list = Book.objects.all()
23
bs = BookSerializers(book_list, many=True)
24
return Response(bs.data)
25
26
def post(self, request):
27
pass
Postmen中的数据
23
1
[
2
{
3
"title": "你好,再见",
4
"price": 99,
5
"pub_date": null,
6
"publish": "苹果出版社",
7
"authors": "<QuerySet [<Author: pontoon>, <Author: toonpon>]>" # 得到一个QuerySet
8
},
9
{
10
"title": "再见,你好",
11
"price": 88,
12
"pub_date": null,
13
"publish": "橘子出版社",
14
"authors": "<QuerySet [<Author: pontoon>]>"
15
},
16
{
17
"title": "谁动了我的奶酪?",
18
"price": 77,
19
"pub_date": null,
20
"publish": "苹果出版社",
21
"authors": "<QuerySet []>"
22
}
23
]
31
1
# 为queryset做序列化
2
class BookSerializers(serializers.Serializer):
3
"""Book表是一个比较复杂的表包含了一对多与多对多"""
4
title = serializers.CharField()
5
price = serializers.IntegerField()
6
pub_date = serializers.DateField()
7
# 这怎么办?
8
# publish = models.ForeignKey("Publish", on_delete=models.CASCADE) # 一对多
9
# authors = models.ManyToManyField("Author") # 多对多
10
publish = serializers.CharField(source="publish.name") # 一对多、类名小写
11
# 多对多的话这个sourse不好使,得到的是Queryset
12
# authors = serializers.CharField(source="authors.all") # 多对多、类名小写.all() 自动执行
13
14
# 多对多这样来整
15
authors = serializers.SerializerMethodField()
16
17
def get_authors(self, obj):
18
temp = []
19
for obj in obj.authors.all():
20
temp.append(obj.name)
21
return temp
22
23
24
class BookView(APIView):
25
def get(self, request):
26
book_list = Book.objects.all()
27
bs = BookSerializers(book_list, many=True)
28
return Response(bs.data)
29
30
def post(self, request):
31
pass
Postmen
28
1
[
2
{
3
"title": "你好,再见",
4
"price": 99,
5
"pub_date": null,
6
"publish": "苹果出版社",
7
"authors": [
8
"pontoon",
9
"toonpon"
10
]
11
},
12
{
13
"title": "再见,你好",
14
"price": 88,
15
"pub_date": null,
16
"publish": "橘子出版社",
17
"authors": [
18
"pontoon"
19
]
20
},
21
{
22
"title": "谁动了我的奶酪?",
23
"price": 77,
24
"pub_date": null,
25
"publish": "苹果出版社",
26
"authors": []
27
}
28
]
这样的数据就比较好
ModelSerialezer
POST请求的数据
37
1
# 为queryset做序列化
2
class BookSerializers(serializers.Serializer):
3
"""Book表是一个比较复杂的表包含了一对多与多对多"""
4
title = serializers.CharField()
5
price = serializers.IntegerField()
6
pub_date = serializers.DateField()
7
# 这怎么办?
8
# publish = models.ForeignKey("Publish", on_delete=models.CASCADE) # 一对多
9
# authors = models.ManyToManyField("Author") # 多对多
10
publish = serializers.CharField(source="publish.pk") # 一对多、类名小写
11
# 多对多的话这个sourse不好使,得到的是Queryset
12
# authors = serializers.CharField(source="authors.all") # 多对多、类名小写.all() 自动执行
13
14
# 多对多这样来整
15
authors = serializers.SerializerMethodField()
16
17
def get_authors(self, obj):
18
temp = []
19
for obj in obj.authors.all():
20
temp.append(obj)
21
return temp
22
23
# 这个地方我们对字段进行了一些列的定制
24
25
26
class BookView(APIView):
27
def get(self, request):
28
...
29
30
def post(self, request):
31
bs = BookSerializers(data=request.data)
32
if bs.is_valid(): # 验证码提交过来的数据是否合格
33
print(bs.validated_data) # 如果是合格的数据走了内置的create()方法,将提交过来的保存至数据库中!
34
bs.save() # 保存
35
return Response(bs.data) # 返回数据
36
else:
37
return Response(bs.errors) # 返回错误
用postmen传数据过来会报错
该咋整,如何将数据保存至数据库中咧?
34
1
class BookSerializers(serializers.ModelSerializer):
2
"""Book表是一个比较复杂的表包含了一对多与多对多"""
3
class Meta:
4
model = Book
5
fields = "__all__"
6
publish = serializers.CharField(source="publish.pk") # 一对多、类名小写
7
8
def create(self, validated_data):
9
"""重写源码中的create方法"""
10
print("validated_data", validated_data)
11
book = Book.objects.create(title=validated_data["title"],
12
price=validated_data['price'],
13
publish_id=validated_data['publish']['pk'],
14
)
15
book.authors.add(*validated_data["authors"])
16
return book
17
18
>>> validated_data {'publish': {'pk': '1'}, 'title': 'java', 'price': 20, 'authors': [<Author: pontoon>, <Author: toonpon>]}
19
20
21
22
class BookView(APIView):
23
def get(self, request):
24
book_list = Book.objects.all()
25
bs = BookSerializers(book_list, many=True)
26
return Response(bs.data)
27
28
def post(self, request):
29
bs = BookSerializers(data=request.data)
30
if bs.is_valid():
31
bs.save()
32
return Response(bs.data)
33
else:
34
return Response(bs.errors)
Postmen在次提交数据
返回成功啦! ,不过这也太吉儿的复杂了把,还得花时间整理!透~
单条数据的get/post请求
url
4
1
# 获取所有数据的URL
2
path('books/', views.BookView.as_view()),
3
# 获取单条数据的URL
4
path('books/<int:pk>', views.BookDetailView.as_view()),
视图
x
1
class BookDetailView(APIView):
2
"""获取单条数据"""
3
def get(self, request, pk):
4
book = Book.objects.get(pk=pk)
5
bs = BookModelSerializers(book)
6
return Response(bs.data)
7
8
def put(self, request, pk):
9
""" 想那张表提交那条数据 """
10
book = Book.objects.get(pk=pk)
11
bs = BookModelSerializers(book, data=request.data)
12
if bs.is_valid():
13
bs.save()
14
return Response(bs.errors)
15
16
def delete(self, request, pk):
17
Book.objects.get(pk=pk).delete()
18
19
return Response()
序列化超链接字段
第二步
效果如图