使用 Django Rest Framework 序列化通用关系,支持写入
Serialize Generic relationships with Django Rest Framework, with write support
我有以下型号:
class TaggedItem(models.Model):
tag = models.SlugField()
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey('content_type', 'object_id')
我正在尝试以一种可以通过 API 端点
分配内容对象的方式序列化此模型
到目前为止我已经这样做了:
class TaggedItemSerializer(serializers.ModelSerializer):
content_object = serializers.RelatedField(read_only=True)
class Meta:
model = TaggedItem
但是这是只读的。如果我删除 read_only 参数,我必须为该字段指定查询集。但是,对于这种通用关系,我有许多不同的模型类型。如果我在序列化程序和模型中的其他地方指定所有可能的模型类型,那么我似乎在复制代码。
我也可以通过 object_id 和 content_type 字段设置内容对象,但是当我这样做时出现错误。
例如:
{
...
object_id: 1,
content_type: 'auth.User'
}
returns "detail": "JSON parse error - Expected object or value"
的 400 响应
如何通过 DRF api 使此 content_object 可写?
像这样覆盖 .to_internal_value
、.validate
和 .create
方法:
from django.apps import apps
class TaggedItemSerializer(serializers.ModelSerializer):
class Meta:
model = TaggedItem
read_only_fields = ('content_type', 'object_id', 'content_object')
def to_internal_value(self, data):
object_id = data.pop('object_id')
content_type = data.pop('content_type')
ret = super(ConfigCalcSerializer, self).to_internal_value(data)
ret['object_id'] = object_id
ret['content_type'] = content_type
return ret
def validate(self, data):
object_id = data.pop('object_id')
content_type = data.pop('content_type')
Model = apps.get_model(content_type)
try:
content_object = Model.objects.get(id=object_id)
except Model.DoesNotExist:
raise serializers.ValidationError('Not found')
else:
data['content_object'] = content_object
return data
def create(self, validate_data):
return TaggedItem.objects.create(**validate_data)
我有以下型号:
class TaggedItem(models.Model):
tag = models.SlugField()
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey('content_type', 'object_id')
我正在尝试以一种可以通过 API 端点
分配内容对象的方式序列化此模型到目前为止我已经这样做了:
class TaggedItemSerializer(serializers.ModelSerializer):
content_object = serializers.RelatedField(read_only=True)
class Meta:
model = TaggedItem
但是这是只读的。如果我删除 read_only 参数,我必须为该字段指定查询集。但是,对于这种通用关系,我有许多不同的模型类型。如果我在序列化程序和模型中的其他地方指定所有可能的模型类型,那么我似乎在复制代码。
我也可以通过 object_id 和 content_type 字段设置内容对象,但是当我这样做时出现错误。
例如:
{
...
object_id: 1,
content_type: 'auth.User'
}
returns "detail": "JSON parse error - Expected object or value"
如何通过 DRF api 使此 content_object 可写?
像这样覆盖 .to_internal_value
、.validate
和 .create
方法:
from django.apps import apps
class TaggedItemSerializer(serializers.ModelSerializer):
class Meta:
model = TaggedItem
read_only_fields = ('content_type', 'object_id', 'content_object')
def to_internal_value(self, data):
object_id = data.pop('object_id')
content_type = data.pop('content_type')
ret = super(ConfigCalcSerializer, self).to_internal_value(data)
ret['object_id'] = object_id
ret['content_type'] = content_type
return ret
def validate(self, data):
object_id = data.pop('object_id')
content_type = data.pop('content_type')
Model = apps.get_model(content_type)
try:
content_object = Model.objects.get(id=object_id)
except Model.DoesNotExist:
raise serializers.ValidationError('Not found')
else:
data['content_object'] = content_object
return data
def create(self, validate_data):
return TaggedItem.objects.create(**validate_data)