django - 向原始数据添加字段以防止序列化错误
问题描述
假设我有两个模型和它们的序列化器,如下所示:
class Billing(models.Model):
...
class Transaction(models.Model):
billing = models.ForeignKey(Billing, null=False, blank=False)
...
class TransactionSerializer(serializers.ModelSerializer):
billing = serializers.PrimaryKeyRelatedField(queryset=Billing.objects.all())
class Meta:
model = Transaction
fields = '__all__'
现在我想要一个端点来将新交易发布到帐单中,如下所示:
post http://address/billings/{id}/transactions [{other fields except billing because the billing exists in the address}]
为此,我编写了一个这样的视图集:
class BillingTransactionList(generics.ListCreateAPIView):
serializer_class = TransactionSerializer
def get_queryset(self):
billing = get_object_or_404(Billing.objects.all(), pk=self.kwargs['pk'])
return Transation.objects.filter(billing=billing)
def perform_create(self, serializer):
billing = get_object_or_404(Billing.objects.all(), pk=self.kwargs['pk'])
return serializer.save(billing=billing)
但是,如果我从请求中获得的数据中不存在计费,则序列化程序将失败,因为它需要请求原始数据中的计费。我有来自端点的计费,我只希望序列化程序接受数据,然后我将添加计费,就像我在perform_create
.
有一个选项可以添加required=False
,TransactionSerializer
但我需要在另一个地方使用这个序列化required=True
程序,还有另一种解决方案来编写另一个序列化程序,但在我的真实示例中,序列化程序是一个大类,我不想再写一次。我正在寻找一个简单的解决方案来忽略数据中计费的消失,让我随时定义它。
我正在使用 django 1.11.3 和 DRF 3.8.2。
解决方案
我认为最好为您的操作使用 2 个不同的序列化程序(在某种程度上,它们有一个父序列化程序,其中包含大部分通用代码)。
但是如果您不想使用 2 个序列化程序解决方案,您可以覆盖该to_internal_value
方法并选择 url 参数(pk)作为billing
字段,如果它在原始数据中为空(另外,因为通用视图将自己传递给您的序列化程序可以访问序列化程序中的 url 参数)。所以:
class TransactionSerializer(serializers.ModelSerializer):
billing = serializers.PrimaryKeyRelatedField(queryset=Billing.objects.all())
class Meta:
model = Transaction
fields = '__all__'
def to_internal_value(self, data):
billing_pk_in_url = self.context['view'].kwargs.get('pk', None)
if 'billing' not in data: ## or any other condition that you want
data['billing'] = billing_pk_in_url
return super().to_internal_value(data)
现在,您甚至不必重写该perform_create
方法:
class BillingTransactionList(generics.ListCreateAPIView):
serializer_class = TransactionSerializer
def get_queryset(self):
billing = get_object_or_404(Billing.objects.all(), pk=self.kwargs['pk'])
return Transation.objects.filter(billing=billing)
推荐阅读
- bash - 使用 CLI 打开新的终端选项卡/窗口
- angular - Angular:根据 ngFor 中的 Select 显示 div
- business-objects - 在 FROM 中使用子查询而不是 WHERE - SAP BO Web Intelligence
- c++ - 总的通用指针类型是什么?
- python-3.x - 如何将嵌套的布尔 SIEM 搜索字符串展平为 python 中的单个 AND 语句?
- python - 检查字符串以获取特定格式的子字符串,如何..?
- sql - 我需要处理重叠日期,但如果结束日期为空,则假定该过程尚未停止
- javascript - 如何在 Firestore 上的文档中添加集合?反应原生
- iis - OWIN 混合身份验证 IIS 问题
- archer - Archer - 如何实现自动发现