十大接口
drf 十大接口
序列化外键字段的覆盖
在序列化类中自定字段,名字与model类中属性名一致,就称为覆盖操作(覆盖的是属性的所有规则:extra kwargs中指定的简易规则、model字段提供的默认规则、数据库唯一约束等那些规则)
外键覆盖字段用PriaryKeyRekatedField来实现,可以做到只读只写、可读可写三种形式
- 只读:read_only=True
- 只写:querset=关键表达 queryset,write_only=True
- 可读可写:queryset=关联表的queryset
- 当外界关联的数据是多个时,需标识many=True条件
class BookModelSerializer(serializers.ModelSerializer):
# 如何覆盖外键字段
# publish = serializers.PrimaryKeyRelatedField(read_only=True) # 只读
# publish = serializers.PrimaryKeyRelatedField(queryset=models.Publish.objects.all(), write_only=True) # 只写
# publish = serializers.PrimaryKeyRelatedField(queryset=models.Publish.objects.all()) # 可读可写
publish = serializers.PrimaryKeyRelatedField(queryset=models.Publish.objects.all())
authors = serializers.PrimaryKeyRelatedField(queryset=models.Author.objects.all(), many=True)
class Meta:
model = models.Book
fields = ('name', 'price', 'image', 'publish', 'authors')
十大接口
# models.py
from django.db import models
# Create your models here.
# 基类:抽象概念,这个是不会完成数据迁移的,目的是提供共有的字段
class BaseModel(models.Model):
is_delete = models.BooleanField(default=False)
# auto_now_add 自动生成时间,不要手动加时间
create_time = models.DateTimeField(auto_now_add=True, )
last_update_time = models.DateTimeField(auto_now=True)
# import datetime
# create_time = models.DateTimeField(default=datetime.datetime.now)
class Meta:
# 单个字段,有索引,联合唯一
# 联合唯一,有联合索引,联合唯一
abstract = True # 不在数据库中建表
class Book(BaseModel):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=32,verbose_name='图书')
price = models.DecimalField(max_digits=5, decimal_places=2,verbose_name='价格')
# db_constraint=False,逻辑上的关联,增删改没问图
publish = models.ForeignKey('Publish', on_delete=models.DO_NOTHING, db_constraint=False,verbose_name='关联出版社')
authors = models.ManyToManyField('Authors', db_constraint=False,verbose_name='关联作者')
class Meta:
verbose_name_plural= '图书表'
def __str__(self):
return self.name
@property
def publish_name(self):
return self.publish.name
def author_list(self):
return [{"name": author.name, "sex": author.get_sex_display()} for author in self.authors.all()]
class Publish(BaseModel):
name = models.CharField(max_length=32,verbose_name='出版社')
addr = models.CharField(max_length=32,verbose_name='地址')
class Meta:
verbose_name_plural='出版社'
def __str__(self):
return self.name
class Authors(BaseModel):
name = models.CharField(max_length=32,verbose_name='姓名')
sex = models.IntegerField(choices=((1, '男'), (2, '女')),verbose_name='性别')
authordetail = models.OneToOneField('AuthorsDetail', db_constraint=False, on_delete=models.CASCADE,verbose_name='关联作者详情')
class Meta:
verbose_name_plural = '作者'
def __str__(self):
return self.name
class AuthorsDetail(BaseModel):
mobile = models.CharField(verbose_name='手机号',max_length=11)
# authors = models.OneToOneField('Authors', on_delete=models.CASCADE,verbose_name='关联作者')
class Meta:
verbose_name_plural = '作者详情'
def __str__(self):
return self.mobile
对于共有的字段我们可以创建一个基类,然后每一个表继承基类,这个基类是抽象的,目的是提供共有的字段,我们展示前端上面的删除,只是逻辑上的删除,后台并不会删除,这个事不会完成数据迁移的,abstract = True
不在数据库中建表,这样可以
二、表断关联
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
单查和群查
class BookGenericAPIView(GenericAPIView):
queryset = Book.objects.all().filter(is_delete=False)
serializer_class = BookModelSerializer
def get(self, request, *args, **kwargs):
pk = kwargs.get('pk')
if pk:
obj = Book.objects.filter(is_delete=False, pk=pk).first()
serializer =self.get_serializer(instance=obj)
return APIResponse(result=serializer.data)
else:
book_list = self.get_queryset()
book_list = self.get_serializer(book_list, many=True)
return APIResponse('100', '成功', data=book_list.data)
单增和群增
def post(self, request, *args, **kwargs):
if isinstance(request.data,dict):
book_ser = self.get_serializer(data=request.data) # 现在这个book_ser 是ListSerializer对象
book_ser.is_valid(raise_exception=True)
book_ser.save()
return APIResponse('100','成功',book_ser.data)
else:
book_ser = self.get_serializer(data=request.data,many=True)
book_ser.is_valid(raise_exception=True)
book_ser.save()
return APIResponse('100', '成功', book_ser.data)
- 这里我们区别单增和群增:request.data是{},群增是[]
- 在校验的时候我们捕获异常,失败就抛出异常,返回给前端
单改和群改
def put(self, request, *args, **kwargs):
if kwargs.get('pk',None):
book = Book.objects.filter(pk=kwargs.get('pk')).first()
book_ser = BookModelSerializer(instance=book, data=request.data, partial=True) # 增多条
book_ser.is_valid(raise_exception=True)
book_ser.save()
return Response(book_ser.data)
else:
# print(request.data)
book_obj = [] # 存放当前书的对象
book_list = []
for item in request.data:
book = Book.objects.filter(pk=item.pop('id'),is_delete=False).first()
book_obj.append(book)
book_list.append(item)
book_ser = self.get_serializer(instance=book_obj,data=book_list,many=True)
book_ser.is_valid(raise_exception=True)
book_ser.save()
return APIResponse('100', '成功', book_ser.data)
单整体该改分析整体该改分析
单整体改:接口:api/books/pk 数据:dict
1 分析request.data数据[{'pk':1,'name':'',publish:1,'authors':[1,2]}]
2 我们还可以从request.data中分离出数据,放在一个列表里面pks
3 pks中存放的pks在数据库中没有对应的数据,或者对应的数据已经删除,这些不合理的pk要剔除
4 pks最终转化得到的列表长度和request.data列表长度一致,否则就是数据有误
5 我们新增的数据使用的是ListSerializer--》create方法
def create(self, validated_data):
self.child是BookModelSerializer对象
print(type(self.child))
return [
self.child.create(attrs) for attrs in validated_data
]
单部修改和群修改
def put(self, request, *args, **kwargs):
if kwargs.get('pk',None):
book = Book.objects.filter(pk=kwargs.get('pk')).first()
book_ser = BookModelSerializer(instance=book, data=request.data, partial=True) # 增多条
book_ser.is_valid(raise_exception=True)
book_ser.save()
return Response(book_ser.data)
else:
# print(request.data)
book_obj = [] # 存放当前书的对象
book_list = []
for item in request.data:
book = Book.objects.filter(pk=item.pop('id'),is_delete=False).first()
book_obj.append(book)
book_list.append(item)
book_ser = self.get_serializer(instance=book_obj,data=book_list,many=True)
book_ser.is_valid(raise_exception=True)
book_ser.save()
return APIResponse('100', '成功', book_ser.data)
分析
单整体改:接口:/books/(pk)/ 数据:dict
群整体改:接口:/books/ 数据:[{pk1, ...}, ..., {pkn, ...}] | {pks: [pk1, ..., pkn], data: [{}, ..., {}]}
这里的群改我们重新写update方法,因为我们最后用的序列化器是ListSerializer,这个没有写update方法
单删和群删
def delete(self,request,*args,**kwargs):
pk = kwargs.get('pk')
pks = []
if pk:
pks.append(pk)
else:
pks = request.data.get('pks')
res = Book.objects.filter(is_delete=False,pk__in=pks).update(is_delete=True) #把is_delete设置成true
if res:
return APIResponse(data={'msg': '删除成功'})
else:
return APIResponse(data={'msg': '没有要删除的数据'})
分析
单删和群删我们共用一个接口,无论是kwargs取过来的值,还是request.data取到的值,把单删的数据pk值放进pks=[]里面我们用一个删除的表
序列化的写法
from rest_framework import serializers
from app01.models import Publish,Book,Authors
class BookListSerializer(serializers.ListSerializer):
def update(self, instance, validated_data):
print(validated_data)
# print(instance)
return [
self.child.update(instance[i],attrs) for i,attrs in enumerate(validated_data)
]
class BookModelSerializer(serializers.ModelSerializer):
class Meta:
model = Book
list_serializer_class = BookListSerializer
fields = ["id", 'name', 'price', 'publish', 'authors', 'publish_name', 'author_list']
extra_kwargs = {
'publish': {'write_only': True},
'authors': {'write_only': True},
'publish_name': {'read_only': True},
'author_list': {'read_only': True},
}
分析重写的update
1 写一个类,继ListSerializer,重写update
2 self.child:是BookModelSerializer对象
3 self.child.update(对象,字典) for attrs in validated_data
4 和BookModelSerializer建立关联,list_serializer_class = BookListSerializer