ORM配合DRF序列化组件使用
ORM建表操作补充
同一表不能有两个自增
class BaseModel(models.Model):
is_delete = models.BooleanField(default=False)
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
help_text : 写提示信息
models.CharField(max_length=32, verbose_name='书名',help_text='提示信息')
class Meta:
verbose_name_plural = '书籍表' # admin后台管理中显示表名
publish = models.ForeignKey(to='Publish',on_delete=models.CASCADE,db_constraint=True)
on_delete: models.CASCADE级联删除 models.DO_NOTHING啥也不做
db_constraint: True 在数据库中不建立实际的表关联,但是ORM语句可以正常用 能优化数据库
djangoadmin后台管理需要在admin中注册
admin.site.register(models.Book)
admin.site.register(models.Publish)
admin.site.register(models.Author)
admin.site.register(models.AuthorDetail)
models.py中写方法,用于跨表查询是展示数据
@property
def publish_name(self):
return self.publish.name
@property
def author_list(self):
author_list = self.authors.all()
return [{'name': author.name, 'sex': author.get_sex_display()} for author in author_list]
ORM 增删查改实操核心源码
models.py
class BaseModel(models.Model):
is_delete = models.BooleanField(default=False, verbose_name="是否删除")
create_time = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
last_update_time = models.DateTimeField(auto_now=True, verbose_name="修改时间")
# 第二种写法
# import datetime
# create_time = models.DateTimeField(default=datetime.datetime.now)
class Meta:
# 抽象表,不在数据库中建表
abstract = True
class Book(BaseModel):
name = models.CharField(max_length=32, verbose_name='书名', help_text='提示信息')
price = models.DecimalField(max_digits=8, decimal_places=2, verbose_name='价格')
publish = models.ForeignKey(to='Publish', on_delete=models.CASCADE, db_constraint=True, verbose_name='出版社')
authors = models.ManyToManyField(to='Author', db_constraint=True, verbose_name='作者')
class Meta:
verbose_name_plural = '书籍表' # admin后台管理中显示表名
def __str__(self):
return self.name # 在admin后台管理上显示书名
@property
def publish_name(self):
return self.publish.name
@property
def author_list(self):
author_list = self.authors.all()
return [{'name': author.name, 'sex': author.get_sex_display()} for author in author_list]
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 Author(BaseModel):
name = models.CharField(max_length=32, verbose_name='作者名')
sex = models.IntegerField(choices=((1, '男'), (0, '女')), verbose_name='性别')
authordetail = models.OneToOneField(to='AuthorDetail', db_constraint=True, on_delete=models.CASCADE,
verbose_name='作者详情')
class Meta:
verbose_name_plural = '作者表'
def __str__(self):
return self.name
class AuthorDetail(BaseModel):
phone = models.CharField(max_length=11)
class Meta:
verbose_name_plural = '作者详情表'
def __str__(self):
return self.phone
views.py
APIView和GenericAPIView和子类怎么选
- GenericAPIView优先级高
# 基于APIView
class BookAPIView(APIView):
def get(self, request, *args, **kwargs):
pk = kwargs.get('pk')
# 查一个
if pk:
book = models.Book.objects.filter(pk=pk).first()
if book:
book_ser = ser.BookModelSerializer(book)
return APIResponse(data=book_ser.data)
return APIResponse(code=102, msg='该数据不存在')
# 查询所有
book_list = models.Book.objects.all().filter(is_delete=False)
book_list_ser = ser.BookModelSerializer(book_list, many=True)
return Response(data=book_list_ser.data)
def post(self, request, *args, **kwargs):
# 增单条
if isinstance(request.data, dict):
book_ser = ser.BookModelSerializer(data=request.data)
book_ser.is_valid(raise_exception=True)
book_ser.save()
# 增多条
elif isinstance(request.data, list):
book_ser = ser.BookModelSerializer(data=request.data, many=True)
# 现在book_ser 是 ListSerializer对象
book_ser.is_valid(raise_exception=True)
book_ser.save()
'''
新增---》ListSerializer--》ListSerializer的create方法
源码:
def create(self, validated_data):
# self.child是BookModelSerializer对象
return [
self.child.create(attrs) for attrs in validated_data
]
'''
else:
return APIResponse(code=102, msg='未知错误')
return APIResponse(data=book_ser.data)
def put(self, request, *args, **kwargs):
if kwargs.get('pk'):
book = models.Book.objects.filter(pk=kwargs.get('pk')).first()
if book:
# partial=True 允许部分修改,相当于在每个字段都加了一个required=False
book_ser = ser.BookModelSerializer(instance=book, data=request.data, partial=True)
# 校验数据是否合法
book_ser.is_valid(raise_exception=True)
book_ser.save()
return APIResponse(data=book_ser.data)
return APIResponse(code=102, msg=f'id值为:`{kwargs.get("pk")}`数据不存在')
book_list = []
modify_data = []
error_list = []
for item in request.data:
pk = item.get('id')
book = models.Book.objects.filter(pk=pk).first()
if book:
item.pop('id')
book_list.append(book)
modify_data.append(item)
else:
error_list.append(item)
# 方案1 for 循环一个个修改,核心点
# for i,si_data in enumerate(modify_data):
# book_ser = ser.BookModelSerializer(instance=book_list[i], data=si_data)
# book_ser.is_valid(raise_exception=True)
# book_ser.save()
# return Response(data='成功')
# 方案2 重写ListSerializer的update方法 推荐使用
book_ser = ser.BookModelSerializer(instance=book_list, data=modify_data, many=True, partial=True)
book_ser.is_valid(raise_exception=True)
book_ser.save()
if error_list:
return APIResponse(code=103, msg='部分信息修改成功', data=book_ser.data,
error={"msg": "下述id值信息不存在", "data": [data for data in error_list]})
return APIResponse(data=book_ser.data)
def delete(self, request, *args, **kwargs):
pk = kwargs.get('pk')
pks = []
if pk:
# 单条删除
pks.append(pk)
else:
# 多条删除,前端给数据
# {'pks':[1,2,3]}
pks = request.data.get('pks')
# 把is_delete设置成true
# ret返回受影响的行数
ret = models.Book.objects.filter(pk__in=pks, is_delete=False).update(is_delete=True)
if ret:
return Response(data={'msg': '删除成功'})
else:
return Response(data={'msg': '没有要删除的数据'})
# 基于GenericAPIView
class BookGenericAPIView(GenericAPIView):
queryset = models.Book.objects.filter(is_delete=False).all()
serializer_class = ser.BookModelSerializer
def get(self, request, *args, **kwargs):
pk = kwargs.get('pk')
if pk:
book = self.get_object()
if book:
book_ser = self.get_serializer(book)
return APIResponse(data=book_ser.data)
return APIResponse(code=102, msg='该数据不存在')
book_list = self.get_queryset()
book_list_ser = self.get_serializer(book_list, many=True)
return APIResponse(data=book_list_ser.data)
def post(self, request, *args, **kwargs):
# 增单条
if isinstance(request.data, dict):
book_ser = self.get_serializer(data=request.data)
book_ser.is_valid(raise_exception=True)
book_ser.save()
# 增多条
elif isinstance(request.data, list):
book_ser = self.get_serializer(data=request.data, many=True)
# 现在book_ser 是 ListSerializer对象
book_ser.is_valid(raise_exception=True)
book_ser.save()
else:
return APIResponse(code=102, msg='未知错误')
return APIResponse(data=book_ser.data)
def put(self, request, *args, **kwargs):
if kwargs.get('pk'):
book = self.get_object()
if book:
# partial=True 允许部分修改,相当于在每个字段都加了一个required=False
book_ser = self.get_serializer(instance=book, data=request.data, partial=True)
# 校验数据是否合法
book_ser.is_valid(raise_exception=True)
book_ser.save()
return APIResponse(data=book_ser.data)
return APIResponse(code=102, msg=f'id值为:`{kwargs.get("pk")}`数据不存在')
book_list = []
modify_data = []
error_list = []
for item in request.data:
pk = item.get('id')
book = models.Book.objects.filter(pk=pk).first()
if book:
item.pop('id')
book_list.append(book)
modify_data.append(item)
else:
error_list.append(item)
book_ser = self.get_serializer(instance=book_list, data=modify_data, many=True, partial=True)
book_ser.is_valid(raise_exception=True)
book_ser.save()
if error_list:
return APIResponse(code=103, msg='部分信息修改成功', data=book_ser.data,
error={"msg": "下述id值信息不存在", "data": [data for data in error_list]})
return APIResponse(data=book_ser.data)
def delete(self, request, *args, **kwargs):
pk = kwargs.get('pk')
pks = []
if pk:
pks.append(pk)
else:
pks = request.data.get('pks')
ret = models.Book.objects.filter(pk__in=pks, is_delete=False).update(is_delete=True)
if ret:
return APIResponse(msg='删除成功')
else:
return APIResponse(msg="没有要删除的数据")
序列化操作补充
Serializer和ModelSerializer选择
- 如果序列化是数据表,尽量使用ModelSerializer
ser.py
# 写一个类,继承ListSerializer,重写update方法实现批量修改
class BookListSerializer(serializers.ListSerializer):
def update(self, instance, validated_data):
# 保存数据
# self.child:是BookModelSerializer对象
# ll=[]
# for i,si_data in enumerate(validated_data):
# ret=self.child.update(instance[i],si_data)
# ll.append(ret)
# return ll
return [
self.child.update(instance[i], attrs) for i, attrs in enumerate(validated_data)
]
class BookModelSerializer(serializers.ModelSerializer):
# 外键字段展示方案一(序列化没问题,反序列化有问题)
# publish = serializers.CharField(source='publish.name')
# 第二种方法,在models中写方法
class Meta:
# 批量增和批量改时,调用自己写的BookListSerializer
list_serializer_class = BookListSerializer
model = models.Book
# fields = '__all__'
# depth = 1 # 展示数据深度,不常用
fields = ('id', 'name', 'price', 'authors', 'publish', 'publish_name', 'author_list')
extra_kwargs = {
'publish': {'write_only': True},
'publish_name': {'read_only': True},
'id': {'read_only': True},
'authors': {'write_only': True},
'author_list': {'read_only': True},
}