一、模型
from django.db import models
# Create your models here.
class Basemodel(models.Model):
create_time = models.DateTimeField(auto_now_add=True)
last_update_time = models.DateTimeField(auto_now=True)
is_delete = models.BooleanField(default=False)
class Meta:
# 表示这个表是虚拟表,不会再数据库中创建
abstract = True
class Book(Basemodel):
name = models.CharField(max_length=32)
price = models.DecimalField(max_digits=5,decimal_places=2)
# db_constraint = False 表示外键关联实际断开,只有逻辑连接
publish = models.ForeignKey(to='Publish',on_delete=models.DO_NOTHING,db_constraint=False)
authors = models.ManyToManyField(to='Author',db_constraint=False)
class Meta:
verbose_name_plural = '书表'
@property
def publish_name(self):
return self.publish.name
def authors_list(self):
# 返回一个作者列表,内部放作者的所有信息[{id:pk,'name':name}]
authors_list = self.authors.all()
return [{'id':author.id,'name':author.name,'phone':author.author_detail.phone} for author in authors_list]
def __str__(self):
return self.name
class Author(Basemodel):
name = models.CharField(max_length=32)
sex = models.IntegerField(choices=((1,'男'),(2,'女'),(3,'其他')))
author_detail = models.OneToOneField(to='Author_detail',on_delete=models.CASCADE,db_constraint=False)
class Meta:
verbose_name_plural = '作者表'
def __str__(self):
return self.name
class Author_detail(Basemodel):
phone = models.IntegerField()
class Publish(Basemodel):
name = models.CharField(max_length=32)
addr = models.CharField(max_length=32)
class Meta:
verbose_name_plural = '出版社表'
def __str__(self):
return self.name
# 二、表断关联
# 1、表之间没有外键关联,但是有外键逻辑关联(有充当外键的字段)
# 2、断关联后不会影响数据库查询效率,但是会极大提高数据库增删改效率(不影响增删改查操作)
# 3、断关联一定要通过逻辑保证表之间数据的安全,不要出现脏数据,代码控制
# 4、断关联
# 5、级联关系
# 作者没了,详情也没:on_delete=models.CASCADE
# 出版社没了,书还是那个出版社出版:on_delete=models.DO_NOTHING
# 部门没了,员工没有部门(空不能):null=True, on_delete=models.SET_NULL
# 部门没了,员工进入默认部门(默认值):default=0, on_delete=models.SET_DEFAULT
二、序列化器
from rest_framework import serializers
from app01 import models
class New_update_ListSerializer(serializers.ListSerializer):
# 重写update方法,用来实现群改的效果
def update(self, instance, validated_data):
return [self.child.update(instance[i],data) for i,data in enumerate(validated_data)]
class Bookserializers(serializers.ModelSerializer):
# 如果要在book表中找到其他表的数据有两种方法
# 方案一、通过source(只能序列化,反序列化出问题)
# publish=serializers.CharField(source='publish.name')
# 方案二、在models中Book表内写获取对应数据的方法
class Meta:
# 父类中会自动把New_update_ListSerializer替代ListSerializer
list_serializer_class = New_update_ListSerializer
model = models.Book
# 针对序列化字段和反序列化字段用不同的方式表示
fields = ('id','name','price','authors','publish_name','publish','authors_list')
extra_kwargs = {
'id':{'read_only':True},
'authors':{'write_only':True},
'publish': {'write_only':True},
'publish_name': {'read_only':True},
'authors_list': {'read_only':True},
}
三、视图
1 单增群增
class BookAPIView(GenericAPIView):
queryset = models.Book.objects.filter(is_delete=False)
serializer_class = sers.Bookserializers
def get(self,request,*args,**kwargs):
pk = kwargs.get('pk')
if pk:
book_ser = self.get_serializer(self.queryset.filter(pk=pk).first())
return Response(book_ser.data)
else:
book_ser = self.get_serializer(self.queryset.all(),many=True)
return Response(data=book_ser.data)
2 单存群存
def post(self,request,*args,**kwargs):
if isinstance(request.data,dict):
book_ser = self.get_serializer(data=request.data)
return Response(book_ser.data)
elif isinstance(request.data,list):
book_ser = self.get_serializer(data=request.data,many=True)
book_ser.is_valid(raise_exception=True)
# 新增---》ListSerializer--》create方法
# def create(self, validated_data):
# self.child是BookModelSerializer对象
# print(type(self.child))
# return [
# self.child.create(attrs) for attrs in validated_data
# ]
book_ser.save()
return Response(book_ser.data)
3 单改群改
# 在提交数据之前,需要确定好数据的格式,需要和前端人员协商
def put(self,request,*args,**kwargs):
id = kwargs.get('pk')
if id:
book_ser = self.get_serializer(self.queryset.filter(pk=id).first(),data=request.data)
book_ser.is_valid(raise_exception=True)
book_ser.save()
return Response(book_ser.data)
else:
# 方式一:传入的数据是[{id:1,xxx}] 循环取出id一条一条修改(常用)
# l = []
# for book in request.data:
# id = book.pop('id')
# book_ser = self.get_serializer(self.queryset.filter(id=id).first(),data=book)
# book_ser.is_valid(raise_exception = True)
# book_ser.save()
# l.append(book_ser.data)
# return Response(l)
# 方式二:通过重写ListSerializer的update方法(不常用)
# 因为我在通过序列化的时候传入many=True,这个时候实例化的类是ListSerializer,我们可以看看它内部的源码
# 得知它写了create方法,也就是我们可以支持群增,但是update的方法是直接抛异常的,也就是我们要使用就必须重写这个方法
# 但是如何让我们重写的类(继承ListSerializer)去替换ListSerializer在序列化中的地位呢?
# 查看ListSerializer父类的__new__方法
# def __new__(cls, *args, **kwargs):
# # We override this method in order to automagically create
# # `ListSerializer` classes instead when `many=True` is set.
# if kwargs.pop('many', False):
# return cls.many_init(*args, **kwargs)
# return super().__new__(cls, *args, **kwargs)
# 如果在实例化的时候传了many=True,那就调用many_init方法
# 而这个方法的最后有这么两句话
# meta = getattr(cls, 'Meta', None)
# list_serializer_class = getattr(meta, 'list_serializer_class', ListSerializer)
# 看看我们自己写的类中有没有Meta类,如果有的话,再看看里面有没有list_serializer_class的赋值
# 如果有的话,这个值对应的类名就代替ListSerializer的地位
# 所以在此我们在class Meta中给他一个参数list_serializer_class= 我们自己重写的类即可
id_list = []
for book in request.data:
id_list.append(book.get('id'))
book_ser = self.get_serializer(self.queryset.filter(id__in = id_list),request.data,many=True)
book_ser.is_valid(raise_exception = True)
book_ser.save()
return Response(book_ser.data)
4 单删群删
def delete(self,request,**kwargs):
id = kwargs.get('pk')
if id:
obj = self.queryset.filter(id=id).update(is_delete = True)
if obj:
return Response({'msg':'删除成功'})
else:
return Response({'msg':'目标不存在'})
else:
# request.data = [1,2,3]
obj = self.queryset.filter(id__in = request.data).update(is_delete = True)
return Response({'msg':'删除成功'})