在序列化程序中编辑外键字段 - 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.novalue = 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的主要内容,如果未能解决你的问题,请参考以下文章

Django 序列化器 - 返回特定字段

在 REST-ful api 中序列化外键字段的最佳实践是啥

在 GET 中隐藏密码字段,但在 Django REST Framework 中隐藏密码字段,其中序列化程序中的 depth=1

通过django rest框架序列化器添加外键数据

如何在序列化程序 django rest 框架中为外键设置源

django admin外键字段选择后如何关联显示另一个字段?