ORM配合DRF序列化组件使用

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},
        }
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

go&Python

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值