在序列化程序中编辑外键字段 - Django Rest Framework
Posted
技术标签:
【中文标题】在序列化程序中编辑外键字段 - Django Rest Framework【英文标题】:Editing the foreign key field in Serializer - Django Rest Framework 【发布时间】:2016-04-10 11:48:33 【问题描述】:我正在使用 Django Rest 框架。我正在使用此建议在自动建议 Select2 dropdown but allow new values by user? 中添加新值。但这对我来说几乎是不可能的。
Payee 是外键字段。如果返回字符串和 '(NEW)' 而不是主键,我需要在 Contacts 模型中创建对象,并且应该将新创建的对象的主键设置为收款人字段。
models.py
class Contacts(models.Model):
no = models.AutoField(primary_key=True)
name = models.CharField(max_length=25)
class Transactions(models.Model):
payee = models.ForeignKey(Contacts,null=True, related_name = 'transactions_payee')
reminder = models.ForeignKey(Reminders, related_name='transaction_reminders',blank=True, null=True)
序列化器.py
class TransactionSerializer(serializers.ModelSerializer):
reminder = ReminderSerializer()
class Meta:
model = Transactions
fields=('pk','payee','reminder'...)
def validate_payee(self, value):
if " (NEW)" not in value:
return value
else:
payee = value.replace(" (NEW)", "")
contact = Contacts.objects.create(name = payee)
value = contact.no
return value
def create(self, validated_data):
... #writable nested serializer for reminder field.
def update(self, instance, validated_data):
... #writable nested serializer for reminder field.
validate_payee 甚至没有被调用。我什至尝试在 create() 中添加相同的逻辑,但是 django 的默认验证器在所有这些之前出现并抛出错误消息说
payee: ["Incorrect type. Expected pk value, received unicode."]
我是 Django 的初学者。我搜索了几乎所有的 *** 问题。没有什么对我有用,或者我在某个地方犯了错误。
【问题讨论】:
【参考方案1】:解决方案 #1
payee: ["Incorrect type. Expected pk value, received unicode."]
发生上述错误是因为 TransactionSerializer 将字段“payee”处理为 ForeignKeyField(如 PK)。
所以当你的 validate_payee 方法被调用而不是返回一个 PK 值时, 您正在返回一个 unicode 字符串。
我认为您正在尝试处理 valdiate_payee 中的收款人作为实例 收款人模式。
如果这是您想要的,那么我的建议是更新 TransactionSerializer 并尝试添加以下行之一:
reminder = ReminderSerializer()
payee = PayeeSerializer() # This is one
payee = ContactSerializer() # Or this one.
执行上述操作确保您的 validate_payee 函数返回一个 联系方式。
如果验证不正确,只需提出 ValidationError (http://www.django-rest-framework.org/api-guide/exceptions/#validationerror)
解决方案 #2
尝试改变:
value = contact.no
value = contact.id
建议,如果您刚开始使用 DRF,要检查您的代码,只需插入:import ipdb; ipdb.set_trace()
这将使用交互式 python shell 设置断点,以便您可以检查该代码是否正在执行,也可以检查变量的当前内容。
如果您想检查是否正在执行 validate_payee,请尝试:
def validate_payee(self, value):
import ipdb; ipdb.set_trace()
if " (NEW)" not in value:
return value
else:
payee = value.replace(" (NEW)", "")
contact = Contacts.objects.create(name = payee)
value = contact.no
return value
希望这能有所帮助。
【讨论】:
首先为了您的推荐,我在 validate_payee() 函数中使用了logger.debug("Inside Validate")
。它根本没有记录。您的解决方案 #1 给出了错误消息 payee: non_field_errors: ["Invalid data. Expected a dictionary, but got unicode."]
。 no
是联系人模型中的主键字段。我也试过payee = serializers.PrimaryKeyRelatedField(queryset=Contacts.objects.all(), source='payee', write_only=True, validators=[validate_payee])
,但错误是validate_payee() takes exactly 1 argument (2 given)
。请帮忙。 :)
好的,我想通了,它没有进入您的验证功能,因为收款人字段中的 TransactionSerializer 需要一个整数。但是您的应用程序也可以发送字符串。我建议您设置 payee=serializers.CharField() 这样您就可以在 TransactionSerializer 中接收几乎所有内容,然后您就可以在验证函数中处理值。
我也试过了。当我使用它时,它会成功验证,删除 '(NEW).但它在 create() 方法中抛出错误,说 payee: Expecting Foreign Key field but got some string....
。我认为必须有一些技巧。
完全没问题,只需覆盖 TransactionSerializer 中的 create 方法即可。在 create 方法中,您只需要从validated_data (def create(self,validated_data)) 中弹出收款人,然后根据您弹出的值创建您的收款人实例。请记住,validated_data 是一个字典,其中包含在 create 方法中创建实例所需的参数,只需确保您的 create 方法返回如下内容:instance = Transactions.objects.create(**validated_data)。
我已经在问题中提到了。当我在 create() 字段中使用逻辑时,django 的默认验证甚至在 create is 之前就已经出现并说payee: ["Incorrect type. Expected pk value, received unicode."]
。以上是关于在序列化程序中编辑外键字段 - Django Rest Framework的主要内容,如果未能解决你的问题,请参考以下文章
在 REST-ful api 中序列化外键字段的最佳实践是啥
在 GET 中隐藏密码字段,但在 Django REST Framework 中隐藏密码字段,其中序列化程序中的 depth=1