基于类的通用视图中重写create()实现保存前自定义逻辑
在Django基于类的通用视图中保存记录前执行自定义逻辑的方法
针对你需要自行生成balance字段值、不依赖请求传入的需求,有几种简洁的实现方式:
方法一:在视图的create方法中修改请求数据
你可以在调用父类create方法前,修改请求的传入数据,添加或覆盖指定字段:
class WalletListCreateAPIView(generics.ListCreateAPIView): queryset = Wallet.objects.all() serializer_class = WalletSerializer def create(self, request, *args, **kwargs): # 复制请求数据(QueryDict默认不可变,需转为可变对象) mutable_data = request.data.copy() # 自定义生成balance值,比如设置初始值为0.00 mutable_data['balance'] = Decimal('0.00') # 替换原请求数据 request.data = mutable_data return super().create(request, *args, **kwargs)
方法二:重写序列化器的create方法(推荐)
将数据处理逻辑放在序列化器中更符合职责分离原则,避免视图逻辑臃肿:
# 序列化器代码 class WalletSerializer(serializers.ModelSerializer): class Meta: model = Wallet fields = ['user', 'address', 'balance', 'slug'] def create(self, validated_data): # 自定义balance值,覆盖请求传入的内容(如果有的话) validated_data['balance'] = Decimal('0.00') # 可替换为你的自定义生成逻辑 # 还能顺便处理其他字段,比如自动生成slug validated_data['slug'] = slugify(validated_data['address']) return super().create(validated_data)
视图无需额外修改,保持原有代码即可。
方法三:利用模型的save方法
如果该自定义逻辑是模型层面的通用规则(比如所有新建Wallet都需要设置初始balance),可以直接重写模型的save方法:
class Wallet(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE) address = models.CharField(max_length=34) balance = models.DecimalField(default=0, max_digits=16, decimal_places=8) slug = models.SlugField(max_length=34, blank=True, null=True) def save(self, *args, **kwargs): # 仅在新建对象时执行自定义逻辑 if not self.pk: self.balance = Decimal('0.00') # 自定义初始值或生成逻辑 self.slug = slugify(self.address) super().save(*args, **kwargs)
这种方式下,视图和序列化器都无需修改,所有创建该模型实例的场景都会自动应用此逻辑。
内容的提问来源于stack exchange,提问作者Liondancer
相关产品推荐
相关产品推荐

