提问者:小点点

django rest框架:contenttype和序列化


我对django rest框架有一个关于泛型关系的小问题,这个泛型关系也用于唯一的约束。

我有这个模型:

class VPC(models.Model):
    name = models.SlugField(null=False, max_length=100)
    deletable = models.BooleanField(null=False, default=True)
    date_created = models.DateTimeField(auto_now_add=True)
    date_modified = models.DateTimeField(auto_now=True)
    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
    object_id = models.PositiveIntegerField()
    content_object = GenericForeignKey('content_type', 'object_id')

    class Meta:
        unique_together = (('name', 'content_type', 'object_id'))

它有一个通用关系和一个唯一的约束:专有网络的名称和通用关系(即所有者)。

以下是序列化程序:

class VPCSerializer(serializers.ModelSerializer):

 class Meta:
    model = VPC
    read_only_fields = ('deletable', 'date_created', 'date_modified')
    fields = ('name', 'deletable')
    lookup_field = 'name'
    validators = [
        UniqueTogetherValidator(
            queryset=VPC.objects.all(),
            fields=('name', 'content_type', 'object_id')
        )
    ]

在字段中,我不把content_type和object_id,因为我不想让用户显示/设置它们。

但是,我必须把它们放在UniqueTobetherValidator中,以避免在创建具有相同帐户/名称的VPC时出现django.db.utils.integrityerror的错误。

但现在,当我尝试创建VPC时,出现了以下错误:

{"object_id":["此字段是必需的。"],"content_type":["此字段是必需的。"]}

所以在我的视图集中。ModelViewSet我试图重写perform_create()以设置对象id和内容类型,但似乎在调用此方法之前引发了错误。

我还尝试重写get_serializer_context(),以返回包含对象id和内容类型的字典,但这两种方法都不起作用。

我花了很多时间在这上面,但我没有发现。那么,我应该重写什么方法才能在序列化器中设置object_id和content_type呢?

谢谢


共1个答案

匿名用户

序列化程序验证在

def create(self, request, *args, **kwargs):

方法不在“执行创建”中

您需要覆盖“创建”方法,并在请求数据中填充“content_type”、“object_id”(将用于初始化序列化器和验证)。

你可以这样做,例如,

def create(self, request, *args, **kwargs):
    if hasattr(request.data, '_mutable'):
        request.data._mutable = True
    request.data['content_type'] = "your_content_type"
    request.data['content_type'] = "your_object_id"

    serializer = VPCSerializer(data=request.data,  request=request)
    serializer.is_valid(raise_exception=True)
    self.perform_create(serializer)

    return Response here..

只需在初始化序列化程序之前填充所需的数据并检查验证,然后使用序列化程序对象保存并返回serilizer.data或任何所需的自定义响应。