多表序列化
# 图书表,出版社表,作者,作者详情 (中间表)
路由
urlpatterns = [
path('admin/', admin.site.urls),
path('books/', views.BookView.as_view()),
path('books/<int:pk>', views.BookDetailView.as_view()),
]
视图类
from .models import Book,Author,AuthorDetail,Publish
from rest_framework.response import Response
from .serializer import BookSerializer
class BookView(APIView):
def get(self, request):
book_list=Book.objects.all()
#序列化
ser=BookSerializer(book_list,many=True)
return Response(ser.data)
# 反序列化的新增
def post(self,request):
ser=BookSerializer(data=request.data)
if ser.is_valid():
ser.save()
return Response({'code':100,'msg':'新增成功'})
else:
return Response({'code':101,'msg':'新增失败','err':ser.errors})
class BookDetailView(APIView):
def get(self, request,pk):
book=Book.objects.all().filter(pk=pk).first()
ser=BookSerializer(book)
return Response(ser.data)
def put(self,request,pk):
book = Book.objects.all().filter(pk=pk).first()
ser = BookSerializer(instance=book,data=request.data)
if ser.is_valid():
ser.save()
return Response({'code':100,'msg':'修改成功'})
else:
return Response({'code':101,'msg':'修改失败','err':ser.errors})
序列化类
from rest_framework import serializers
# 相对导入---->一个py文件中如果使用相对导入,这个文件不能以脚本运行
from .models import Book
# # 绝对导入
# from app01.models import Book
class BookSerializer(serializers.ModelSerializer):
class Meta:
model=Book
# fields="__all__"
fields=['nid','name','price', 'publish_detail', 'author_list', 'publish','authors']
# depth 不要用 --->外键关联一层,我建议不要超过3 不可控,比如我们只想要某几个字段
# depth=1
extra_kwargs={
'publish':{'write_only':True},
'authors': {'write_only': True},
}
# 方式一:重写字段+必须配合一个方法,方法返回啥,该字段就是什么--->该字段只能序列化
publish_detail=serializers.SerializerMethodField(read_only=True)
def get_publish_detail(self,obj):
# 就是当前 book对象
print(obj)
# return obj.publish.name
return {'name':obj.publish.name,'city':obj.publish.city}
# 方式二:在表模型models中写方法,在序列化类中写到fields中
# 把所有的作者:作者名字和作者addr
# 方式一
author_list=serializers.SerializerMethodField(read_only=True)
def get_author_list(self,obj):
# 作者有多个,先拿到所有作者,---》正向查询
author_list=[]
for author in obj.authors.all():
author_list.append({'name':author.name,'addr':author.author_detail.addr})
return author_list
模型类
from django.db import models
# Create your models here.
class Book(models.Model):
nid = models.AutoField(primary_key=True)
name = models.CharField(max_length=32)
price = models.DecimalField(max_digits=5, decimal_places=2)
# publish_date = models.DateField(null=True)
#关联关系
publish = models.ForeignKey(to='Publish',to_field='nid',on_delete=models.CASCADE)
authors=models.ManyToManyField(to='Author') #自动生成中间表
def __str__(self):
return self.name
# def publish_detail(self):
# return {'name':self.publish.name,'email':self.publish.email}
# 作者详情
# def author_list(self):
# author_list=[]
# for author in self.authors.all():
# author_list.append({'name':author.name,'addr':author.author_detail.addr})
# return author_list
class Author(models.Model):
nid = models.AutoField(primary_key=True)
name = models.CharField(max_length=32)
age = models.IntegerField()
author_detail = models.OneToOneField(to='AuthorDetail',on_delete=models.CASCADE)
'''
on_delete可以选择的请情况
-models.CASCADE 级联删除
-models.SET_NULL 关联字段置为空 null=True
-models.SET_DEFAULT 关联字段设为默认值 default=0
-models.DO_NOTHING 由于数据库有约束会报错,去掉外键关系(公司都不建立外键)
-on_delete=models.SET(值,函数内存地址) 设置上某个值,或者运行某个函数
'''
class AuthorDetail(models.Model):
nid = models.AutoField(primary_key=True)
telephone = models.BigIntegerField()
birthday = models.DateField()
addr = models.CharField(max_length=64)
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
请求与响应
请求
# django ---->请求对象----》request
# django ---->响应对象----》render,HttpResponse,Redirect,JsonResponse---》本质都是HttpResponse
# drf中---》请求对象----》新的request---》drf的Request类的对象
# drf的请求对象
-request.data
-request.query_params
-request.FILES
# 控制前端传入的编码格式---》默认 :urlencoded,form-data,json
# 全局生效
-项目配置文件中加入
REST_FRAMEWORK = {
'DEFAULT_PARSER_CLASSES':[
'rest_framework.parsers.JSONParser', # 能够解析json
'rest_framework.parsers.FormParser', # 能够解析urlencoded
'rest_framework.parsers.MultiPartParser', #能够解析form-data
],
}
# 局部生效---》视图类中配置
class BookView(APIView):
parser_classes = [JSONParser,]
# 优先级:先找 视图类---》项目配置文件----》drf配置文件
响应
from rest_framework.response import Response
#初始化对象,传入的参数,response对象的属性
data=None, # 要序列化的数据,字典,列表,字符串
status=None, # http响应状态码
headers=None, # 响应头---》字典
-------最重要的-----
template_name=None, #模板名字---》浏览器看的时候,看到好看的页面,postman看,纯json
content_type=None # 默认json格式,前后端分离项目,前端传用json,后端响应也用json格式
# 浏览器看的时候,看到好看的页面,postman看,纯json----》想控制,都是json格式,无论是浏览器还是postman
# 全局生效
-项目配置文件中加入
REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES':[
'rest_framework.renderers.JSONRenderer', #json格式
'rest_framework.renderers.BrowsableAPIRenderer', #浏览器格式
],
}
# 局部生效---》视图类中配置
class BookView(APIView):
renderer_classes = [JSONRenderer,BrowsableAPIRenderer]
# 优先级:先找 视图类---》项目配置文件----》drf配置文件
视图介绍
views.py
from django.shortcuts import render
from rest_framework.views import APIView
from .models import Book, Publish, Author, AuthorDetail
from .serializer import BookSerializer, PublishSerializer
from rest_framework.views import Response
# Create your views here.
class MyView(APIView):
quest = None
serializer_class = None
class ListModelMixin():
# quest = Book.objects.all()
# serializer_class = BookSerializer
def get(self, request, **kwargs):
if kwargs:
model_obj = self.quest.filter(pk=kwargs.get('pk'))
ser = self.serializer_class(instance=model_obj)
return Response(ser.data)
model_list = self.quest
ser = self.serializer_class(instance=model_list, many=True)
return Response(ser.data)
def post(self, request):
ser = self.serializer_class(data=request.data)
if ser.is_valid():
ser.save()
return Response({'msg': '新增成功'})
else:
return Response({'msg': '新增失败', 'err': ser.errors})
def put(self, request, **kwargs):
model_obj = self.quest.filter(pk=kwargs.get('pk')).first()
ser = self.serializer_class(instance=model_obj, data=request.data)
if ser.is_valid():
ser.save()
return Response({'msg': '修改成功'})
else:
return Response({'msg': '修改失败', 'err': ser.errors})
def delete(self, request, **kwargs):
self.quest.filter(pk=kwargs.get('pk')).delete()
return Response({'msg': "删除成功"})
class BookAPIView(MyView, ListModelMixin):
quest = Book.objects.all()
serializer_class = BookSerializer
def get(self, request, **kwargs):
print(type(self))
return super().get(request, **kwargs)
def post(self, request):
return super().post(request)
def put(self, request, **kwargs):
return super().put(request, **kwargs)
def delete(self, request, **kwargs):
return super().delete(request, **kwargs)
class PublishAPIView(MyView, ListModelMixin):
quest = Publish.objects.all()
serializer_class = PublishSerializer
def get(self, request, **kwargs):
return super().get(request, **kwargs)
def post(self, request):
return super().post(request)
def put(self, request, **kwargs):
return super().put(request, **kwargs)
def delete(self, request, **kwargs):
return super().delete(request, **kwargs)
serializer.py
from rest_framework import serializers
from .models import Book, Publish
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = ['nid', 'name', 'price', 'publish_detail', 'author_detail', 'publish', 'authors']
extra_kwargs = {
'publish': {'write_only': True},
'authors': {'write_only': True}
}
publish_detail = serializers.SerializerMethodField(read_only=True)
def get_publish_detail(self, book_obj):
return {'name': book_obj.publish.name, 'city': book_obj.publish.city}
author_detail = serializers.SerializerMethodField(read_only=True)
def get_author_detail(self, book_obj):
author_list = []
for author in book_obj.authors.all():
author_list.append({'name': author.name, 'addr': author.author_detail.addr})
return author_list
class PublishSerializer(serializers.ModelSerializer):
class Meta:
model = Publish
fields = ['name', 'city', 'book_list']
extra_kwargs = {
'publish': {'write_only': True},
'authors': {'write_only': True}
}
book_list = serializers.SerializerMethodField(read_only=True)
def get_book_list(self, publish_obj):
author_list = []
for book in publish_obj.book_set.all():
author_list.append({'name': book.name, 'price': book.price})
return author_list