1 多表关联的序列化和反序列化
1.1 序列化类
from rest_framework import serializers
from .models import Book, Publish, Author, AuthorDetail
# class BookSerializer(serializers.ModelSerializer):
# class Meta:
# model = Book
# fields = ['id', 'title', 'price', 'publish', 'authors', 'publish_detail',
# 'author_detail'] # 字段可以是属性,也可以是方法(是方法返回值)
# # depth=1 # 深度查一层,官方建议不大于10,正常不超过3,不建议用
# extra_kwargs = {'publish': {'write_only': True},
# 'authors': {'write_only': True},
# 'publish_detail': {'read_only': True},
# 'author_detail': {'read_only': True}
# }
# # 把publish显示出版社的名字和地址
# # 方式一:在表模型中写方法,在序列化类的fields声明一下就可以
# # 方法二:在序列化类中写
# class BookSerializer(serializers.ModelSerializer):
# class Meta:
# model = Book
# # 写在BookSerializer的类属性,也需要在fields中注册一下
# fields = ['id', 'title', 'price', 'publish', 'authors', 'publish_detail',
# 'author_detail'] # 字段可以是属性,也可以是方法(是方法返回值)
# # depth=1 # 深度查一层,官方建议不大于10,正常不超过3,不建议用
# extra_kwargs = {'publish': {'write_only': True},
# 'authors': {'write_only': True},
# }
#
# # 把publish显示出版社的名字和地址
# # 方式一:在表模型中写方法,在序列化类的fields声明一下就可以
# # 方法二:在序列化类中写
# publish_detail = serializers.SerializerMethodField(
# read_only=True) # 这个字段需要配合一个方法,方法必须叫get_字段名,方法返回什么,publish_detail就是什么
#
# def get_publish_detail(self, obj):
# # obj就是当前序列化到的对象,就是book对象
# return {'name': obj.publish.name, 'address': obj.publish.address}
#
# author_detail = serializers.SerializerMethodField(read_only=True)
#
# def get_author_detail(self, obj):
# author_list = obj.authors.all()
# author_dict_list = []
# for author in author_list:
# author_dict_list.append({'name': author.name, 'sex': author.get_sex_display()})
# return author_dict_list
class PublishSerializer(serializers.ModelSerializer):
class Meta:
model = Publish
# fields = ['id']
fields = '__all__'
class AuthorSerializer(serializers.ModelSerializer):
class Meta:
model = Author
fields = "__all__"
class AuthorDetailSerializer(serializers.ModelSerializer):
class Meta:
model = AuthorDetail
fields = "__all__"
class BookSerializer(serializers.ModelSerializer):
publish = PublishSerializer()
authors = AuthorSerializer(many=True) # 多条,一定要加一个 many=True
class Meta:
model = Book
# 写在BookSerializer的类属性,也需要在fields中注册一下
fields = ['id', 'title', 'price', 'publish', 'authors'] # 字段可以是属性,也可以是方法(是方法返回值)
# depth=1 # 深度查一层,官方建议不大于10,正常不超过3,不建议用
extra_kwargs = {'publish': {'write_only': True},
'authors': {'write_only': True},
}
# 把publish显示出版社的名字和地址
# 方式一:在表模型中写方法,在序列化类的fields声明一下就可以
# 方法二:在序列化类中写
# 方式三:通过子序列化
1.2 视图
from .models import Book, AuthorDetail, Author
from .seriazlizer import BookSerializer
class BookView(APIView):
def get(self, request):
book_list = Book.objects.all()
ser = BookSerializer(instance=book_list, many=True)
return Response(data=ser.data)
def post(self, request):
ser = BookSerializer(data=request.data)
if ser.is_valid():
ser.save()
return Response(ser.data)
else:
return Response(ser.errors)
# ser.is_valid(raise_exception=True)
class BookDetailView(APIView):
def get(self, request, pk):
book = Book.objects.all().filter(pk=pk).first()
ser = BookSerializer(instance=book)
return Response(data=ser.data)
def put(self, request, pk):
book = Book.objects.all().filter(pk=pk).first() # 数据不存在,None,如果instance是None,ser.save-->新增
ser = BookSerializer(data=request.data, instance=book)
if ser.is_valid():
ser.save()
return Response(ser.data)
else:
return Response(ser.errors)
def delete(self, request, pk):
res = Book.objects.all().filter(pk=pk).delete() # 返回影响的行数的元组
print(res) #
if res[0] >= 1:
return Response()
else:
return Response('要删除的数据不存在')
1.3 模型层
from django.db import models
# 图书表 出版社 作者 作者详情 图书和作者的多对多表
#
# 一对多:关系一旦确立,关联字段写在多的一方
# 多对多:需要有中间表
class Book(models.Model):
title = models.CharField(max_length=32)
price = models.DecimalField(max_digits=5, decimal_places=2)
# on_delete:
# models.CASCADE # 级联删除
# models.DO_NOTHING # 什么都不做
# models.SET_DEFAULT #设置为默认值
# models.SET_NULL # 设置为空
# models.SET #可以写一个函数内存地址,删除的时候,触发这个函数执行
publish = models.ForeignKey(to='Publish', on_delete=models.SET_NULL, null=True)
authors = models.ManyToManyField(to='Author')
# @property # 加不加都行
# def publish_detail(self):
# return {'name': self.publish.name, 'address': self.publish.address}
#
# # 作者详情 在列表套字典
# def author_detail(self):
# # 获取所有作者
# author_list = self.authors.all()
# author_dict_list = []
# for author in author_list:
# author_dict_list.append({'name': author.name, 'sex': author.get_sex_display()})
# return author_dict_list
class Publish(models.Model):
name = models.CharField(max_length=16)
address = models.CharField(max_length=64)
class Author(models.Model):
name = models.CharField(max_length=16)
sex = models.IntegerField(choices=[(0, '男'), (1, '女')], default=0)
class AuthorDetail(models.Model):
mobile = models.CharField(max_length=11)
# OneToOneField 本质就是 ForeignKey+unique
author = models.OneToOneField(to='Author', on_delete=models.CASCADE)
# author = models.ForeignKey(to='Author', on_delete=models.CASCADE,unique=True)
1.4 路由
urlpatterns = [
# path('admin/', admin.site.urls),
path('publish/', views.PublishView.as_view()),
path('publish/<int:pk>', views.PublishDetailView.as_view()),
path('book/', views.BookView.as_view()),
path('book/<int:pk>', views.BookDetailView.as_view()),
]
2 请求与响应
2.1 Request
# 属性:
request.data # 基于django中的request进行的二次封装,可以从request.data获取所有的数据
request.query_params
request._request 原来的request
request.method --->就是使用了原来的request的method 通过重写 __getattr__魔法方法实现的
# 默认情况下post提交数据,可以三种方式(form-data,urlencoded,json),都能处理
# 我们只允许接口接收json格式,其他格式不支持
# 方式一:全局配置,在配置文件中
REST_FRAMEWORK = {
# 默认能够解析的编码方式
'DEFAULT_PARSER_CLASSES': (
'rest_framework.parsers.JSONParser', # json的
# 'rest_framework.parsers.FormParser', # urlencoded
# 'rest_framework.parsers.MultiPartParser' # form-data
)
}
# 局部配置:(视图类)
class PublishView(APIView):
parser_classes = [FormParser,] # 优先级更高
# 优先级:先用视图类自己的,再用配置文件---》drf的默认配置
2.1 响应 Response
# 属性:
data:返回给前端的数据,可以是字典,列表,字符串
status:响应状态码,1xx 2xx 3xx 4xx 5xx
template_name : 不用,替换模板
headers=None :响应头
#默认用浏览器可以看到页面,用postman可以看到jon
#只能显示json
# 方式一:全局配置,在配置文件中
REST_FRAMEWORK = {
# 使用的渲染类
'DEFAULT_RENDERER_CLASSES': (
'rest_framework.renderers.JSONRenderer',
# 'rest_framework.renderers.BrowsableAPIRenderer',
)
}
# 局部配置:(视图类)
class PublishView(APIView):
renderer_classes = [JSONRenderer,]
# 优先级:先用视图类自己的,再用配置文件---》drf的默认配置
3 视图组件(重点)
3.1 两个视图基类
##### 通过继承GenericAPIView 写5个接口
from rest_framework.views import APIView
from rest_framework.generics import GenericAPIView # 继承APIView,写了几个类属性
'''
# 类属性
queryset = None # 所有数据
serializer_class = None # 序列化的类
lookup_field = 'pk' # 查询单条转换器的字段
# 三个方法
self.get_queryset() # 获取所有数据
self.get_serializer # 获取序列化类
self.get_object() # 获取单条
'''
from rest_framework.mixins import RetrieveModelMixin,ListModelMixin,CreateModelMixin
class PublishView(GenericAPIView):
queryset = Publish.objects.all()
serializer_class = PublishSerializer
def get(self, request):
obj = self.get_queryset()
ser = self.get_serializer(instance=obj, many=True)
return Response(data=ser.data)
def post(self, request):
ser = self.get_serializer(data=request.data)
if ser.is_valid():
ser.save()
return Response(ser.data)
else:
return Response(ser.errors)
# ser.is_valid(raise_exception=True)
class PublishDetailView(GenericAPIView):
queryset = Publish.objects.all()
serializer_class = PublishSerializer
def get(self, request, pk):
obj = self.get_object() # 获取单条,根据pk
ser = PublishSerializer(instance=obj)
return Response(data=ser.data)
def put(self, request, pk):
obj = self.get_object() # 数据不存在,None,如果instance是None,ser.save-->新增
ser = self.get_serializer(data=request.data, instance=obj)
if ser.is_valid():
ser.save()
return Response(ser.data)
else:
return Response(ser.errors)
def delete(self, request, pk):
res = self.get_object().delete() # 返回影响的行数的元组
print(res) #
if res[0] >= 1:
return Response()
else:
return Response('要删除的数据不存在')