python - 在 DRF 中序列化自定义相关字段

标签 python json django serialization django-rest-framework

我正在尝试制作一个具有嵌套“多对多”关系的序列化程序。目标是获得一个包含序列化相关对象数组的序列化 JSON 对象。模型看起来像这样(名称更改,结构保留)

from django.contrib.auth.models import User

PizzaTopping(models.Model):
    name = models.CharField(max_length=255)
    inventor = models.ForeignKey(User)

Pizza(models.Model):
    name = models.CharField(max_length=255)
    toppings = models.ManyToManyField(PizzaTopping)

传入的 JSON 看起来像这样

{
  "name": "My Pizza",
  "toppings": [
    {"name": "cheese", "inventor": "bob"},
    {"name": "tomatoes", "inventor": "alice"}
  ]
}

我当前的序列化程序代码如下所示

class ToppingRelatedField(RelatedField):
    def get_queryset(self):
        return Topping.objects.all()

    def to_representation(self, instance):
        return {'name': instance.name, 'inventor': instance.inventor.username}

    def to_internal_value(self, data):
        name = data.get('name', None)
        inventor = data.get('inventor', None)
        try:
            user = User.objects.get(username=inventor)
        except Setting.DoesNotExist:
            raise serializers.ValidationError('bad inventor')
        return Topping(name=name, inventor=user)

class PizzaSerializer(ModelSerializer):
    toppings = ToppingRelatedField(many=True)

    class Meta:
        model = Pizza
        fields = ('name', 'toppings')

似乎因为我为自定义字段定义了 to_internal_value() ,它应该自动创建/更新多对多字段。但是,当我尝试创建比萨饼时,出现“无法添加”:字段“pizzatopping”的值为 None”ValueError。看起来在某个深处,Django 决定多对多字段应该由模型名称调用。否则我该如何说服它?

编辑 #1:看起来这可能是 Django 或 DRF 某处的真正错误。 DRF 似乎在做正确的事情,它检测到它正在处理 ManyToMany 字段并尝试使用自定义字段从数据中创建浇头并将它们添加到比萨饼中。由于它只有一个披萨实例和一个字段名称,因此它使用 setattr(pizza, 'toppings', toppings) 来完成它。 Django 似乎在做正确的事。 __set__ 已定义,似乎发现它需要在管理器中使用 add() 方法。但在此过程中的某个地方,字段名称“toppings”丢失并被默认值取代。这是“小写的相关型号名称”。

编辑 #2:我找到了解决方案。一旦我被允许,我会在答案中记录它。似乎 RelatedField 子类中的 to_internal_value() 方法需要返回已保存的 Topping 实例,以便 ManyToMany 事物正常工作。现有文档显示相反的情况,此链接 ( http://www.django-rest-framework.org/api-guide/fields/#custom-fields) 该示例清楚地返回未保存的实例。

最佳答案

似乎有一个未记录的要求。对于使用自定义 ManyToMany 字段的写操作,自定义字段类 to_internal_value() 方法需要在返回实例之前保存它。 DRF 文档省略了这一点,创建自定义字段的示例(在 http://www.django-rest-framework.org/api-guide/fields/#custom-fields 处)显示了返回未保存实例的方法。我将更新我与 DRF 团队一起打开的问题。

关于python - 在 DRF 中序列化自定义相关字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39706882/

相关文章:

python - 在 Python 中以 50 block 的形式从列表中打印项目

javascript - jQuery ajax (json) 调用的内存泄漏

PHP PDO 正在将 javascript 对象(ajax)中的字符串保存为空字段

javascript - 如何在浏览器中存储 JWT?

python - 在 django 中使用 pre_save 时取消保存模型

python - Django Serializer 从 post 访问 json 数据(字符串索引必须是整数)

python - Keras准确率和实际准确率正好相反

python - 如何编辑allauth的urls.py?

python - 在 Django 1.4 中使用命名 url 模式会引发错误

python - 如何在 Python 中使用方法引用方法名称?