You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

DRF中创建对象时如何优雅修改关联对象状态?

更规范的DRF实现:创建预约时修改书籍可用性

原代码的问题点

  1. perform_create方法签名错误:DRF中该方法的参数是serializer而非request,原写法会触发报错
  2. 冗余数据库查询:手动从request.data提取ID查询书籍,完全可以直接利用已创建的Reservation实例关联的Book对象
  3. 未处理并发风险:多请求同时预约同一本书时,可能出现超卖问题

优化方案1:修正视图层逻辑(推荐)

直接借助序列化器创建好的Reservation实例操作关联Book,同时用原子事务保证数据一致性:

from django.db import transaction
from rest_framework import viewsets

class ReservationViewSet(viewsets.ModelViewSet):
    queryset = ReservationModel.objects.all()
    serializer_class = ReservationSerializer
    permission_classes = []  # 修正原代码拼写错误:permission_classess → permission_classes

    def perform_create(self, serializer):
        # 原子事务确保预约创建与书籍状态修改要么同时成功,要么同时回滚
        with transaction.atomic():
            reservation = serializer.save()
            # 直接通过关联对象获取Book,避免额外查询
            book = reservation.book
            book.is_available = False
            book.save()

优化方案2:将逻辑内聚到序列化器

如果希望把业务逻辑封装在序列化层,可重写ReservationSerializer的create方法:

from django.db import transaction
from rest_framework import serializers

class ReservationSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = ReservationModel
        fields = ["reserved_by", "book", "started_at", "valid_until"]

    def create(self, validated_data):
        with transaction.atomic():
            reservation = super().create(validated_data)
            book = reservation.book
            book.is_available = False
            book.save()
            return reservation

额外优化建议

  • 封装模型层逻辑:在BookModel中添加方法封装状态修改,进一步解耦业务代码
    class BookModel(models.Model):
        # ... 原有字段
        def mark_as_unavailable(self):
            self.is_available = False
            self.save()
    
    之后在视图或序列化器中直接调用book.mark_as_unavailable()即可
  • 修正原代码中permission_classess的拼写错误,正确写法为permission_classes

内容的提问来源于stack exchange,提问作者dawid.pawlowski

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 14:35:59