原生serializer的使用
from django.core.serializers import serialize
class StudentView(APIView):
def get(self, request):
origin_students = Student.objects.all()
serialized_students = serialize("json", origin_students)
return HttpResponse(serialized_students)
DRF解析器组件
使用:
#1. 引入模块
from rest_framework.views import APIView
#2. 继承APIView
class LoginView(APIView):
parser_classes = [FormParser]
def get(self, request):
return render(request, 'parserver/login.html')
# .3. 直接request.data就可以获取json数据
def post(self, request):
# request是被drf封装的新对象,基于django的request
# request.data是一个property,用于对数据进行校验
# request.data最后会找到self.parser_classes中的解析器
# 来实现对数据进行解析
print(request.data) # {'username': 'alex', 'password': 123}
return JsonResponse({"status_code": 200, "code": "OK"})
解释器组件源码流程
序列化组件
定义几个model
from django.db import models
# Create your models here.
class Publish(models.Model):
nid = models.AutoField(primary_key=True)
name = models.CharField(max_length=32)
city = models.CharField(max_length=32)
email = models.EmailField()
def __str__(self):
return self.name
class Author(models.Model):
nid = models.AutoField(primary_key=True)
name = models.CharField(max_length=32)
age = models.IntegerField()
def __str__(self):
return self.name
class Book(models.Model):
title = models.CharField(max_length=32)
publishDate = models.DateField()
price = models.DecimalField(max_digits=5, decimal_places=2)
publish = models.ForeignKey(to="Publish", to_field="nid", on_delete=models.CASCADE)
authors = models.ManyToManyField(to="Author")
def __str__(self):
return self.title
设计url,请求接口
GET接口
url:
from django.urls import re_path
from serializers import views
urlpatterns = [
re_path(r'books/$', views.BookView.as_view())
]
新建一个名为app_serializers.py的模块,将所有的序列化的使用集中在这个模块里面,对程序进行解耦:
from rest_framework import serializers
from .models import Book
#1.定义序列化类
class BookSeriazlizer(seriazlizers.Serializer):
#2.定义需要返回的字段(字段类型可以与model中的类型不一致,参数也可以调整),
字段名称必须与model中的一致
title = serializers.CharField(max_length=128)
publish_date = serializers.DateTimeField()
price = serializers.DecimalField(max_digits=5, decimal_places=2)
publish = serializers.CharField(max_length=32)
authors = serializers.CharField(max_length=32)
视图类,使用序列化组件
from rest_framework.views import APIView
from rest_framework.response import Response
from .models import Book
from .app_serializer import BookSerializer
class BookView(APIView):
def get(self,request):
#3. GET接口逻辑中,获取QuerySet
origin_books = Book.objects.all()
#4.开始序列化 ,many默认为False,若返回的数据是个多个对象集合,需改为True
serialized_books = BookSerializer(origin_books,many=True)
return Response(serialized_books.data)
下面是通过POSTMAN请求该接口后的返回的测试数据,除ManyToManyField字段不是想要的外,其他的都没有任何问题:
[
{
"title": "Python入门",
"publishDate": null,
"price": "119.00",
"publish": "浙江大学出版社",
"authors": "serializers.Author.None"
},
{
"title": "Python进阶",
"publishDate": null,
"price": "128.00",
"publish": "清华大学出版社",
"authors": "serializers.Author.None"
}
]
若当字段定义为多个参数时,比如authors.all,取出来的结果将是一个querset,对前端来书,这样的数据不太友好,稍微改进下
class BookSerializer(serializers.Serializer):
title = serializers.CharField(max_length=32)
price = serializers.DecimalField(max_digits=5, decimal_places=2)
publishDate = serializers.DateField()
publish = serializers.CharField()
publish_name = serializers.CharField(max_length=32, read_only=True, source='publish.name')
publish_email = serializers.CharField(max_length=32, read_only=True, source='publish.email')
# authors = serializers.CharField(max_length=32, source='authors.all')
authors_list = serializers.SerializerMethodField()
def get_authors_list(self, authors_obj):
authors = list()
for author in authors_obj.authors.all():
authors.append(author.name)
return authors
# 注:get_必须与字段名称一致,否则会报错
POST接口设计
def post(self, request):
verified_data = BookSerializer(data=request.data)
if verified_data.is_valid():
book = verified_data.save()
# 可写字段通过序列化添加成功之后需要手动添加只读字段
authors = Author.objects.filter(nid__in=request.data['authors'])
book.authors.add(*authors)
return Response(verified_data.data)
else:
return Response(verified_data.errors)
多对多字段同样需要自己手动来获取
def get_authors_list(self, book_obj):
author_list = list()
for author in book_obj.authors.all():
author_list.append(author.name)
return author_list
def create(self, validated_data):
# {'title': 'Python666', 'price': Decimal('66.00'), 'publish': '2'}
validated_data['publish_id'] = validated_data.pop('publish')
book = Book.objects.create(**validated_data)
return book
def update(self, instance, validated_data):
# 更新数据会调用该方法
instance.title = validated_data.get('title', instance.title)
instance.publishDate = validated_data.get('publishDate', instance.publishDate)
instance.price = validated_data.get('price', instance.price)
instance.publish_id = validated_data.get('publish', instance.publish.nid)
instance.save()
return instance
感觉还是有点麻烦,若字段很多,写序列化也是一种负担,更加简单的方式如下:
# 继承ModelSerializer
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = ('title',
'price',
'publish',
'authors',
'author_list',
'publish_name',
'publish_city'
)
extra_kwargs = {
'publish': {'write_only': True},
'authors': {'write_only': True}
}
publish_name = serializers.CharField(max_length=32, read_only=True, source='publish.name')
publish_city = serializers.CharField(max_length=32, read_only=True, source='publish.city')
author_list = serializers.SerializerMethodField()
def get_author_list(self, book_obj):
# 拿到queryset开始循环 [{}, {}, {}, {}]
authors = list()
for author in book_obj.authors.all():
authors.append(author.name)
return authors
详细步骤:
- 继承ModelSerializer:不再继承Serializer
- 添加extra_kwargs类变量:extra_kwargs = {‘publish’: {‘write_only’: True}}