gpt4 book ai didi

mysql - 使用 ManyToManyField 序列化模型时出现 Django REST 错误

转载 作者:可可西里 更新时间:2023-11-01 07:08:56 24 4
gpt4 key购买 nike

我使用 Django-REST 包在 Django 服务器上创建了一个对软件产品构建中的一组文件进行建模的类。设计是文件组(一个 Depot 实例)应该能够分配给多个 Build 实例(例如,“alpha”和“beta”构建使用相同的完全相同的音频文件 depot)。但是,在创建 depot 时,它是作为在客户端上创建单个 Build 的一部分而创建的;只是稍后,实用程序脚本将允许将现有 Depot 添加到其他构建中。

对我来说,Depot 类应该用 ManyToManyField 表示这种关系似乎很自然。问题是序列化程序似乎不知道如何处理这个 ManyToManyField。我尝试了几种解决方法,但每种方法都有自己的错误。我试过让我的 DepotSerializer 是 rest_framework.serializers.Serializerrest_framework.serializers.ModelSerializer ,但这似乎与这个问题基本无关。

模型.py:

class Depot(models.Model):
name = models.CharField(max_length=64)
builds = models.ManyToManyField(Build)

TYPE_EXECUTABLE = 0
TYPE_CORE = 1
TYPE_STREAMING = 2
depot_type = models.IntegerField(choices = (
(TYPE_EXECUTABLE, 'Executable'),
(TYPE_CORE, 'Core'),
(TYPE_STREAMING, 'Streaming'),
))

def __str__(self):
return self.name

View .py:
class DepotCreate(mixins.CreateModelMixin,
generics.GenericAPIView):
serializer_class = DepotSerializer
queryset = Depot.objects.all()

def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs)

Serializers.py 版本 1:
class DepotSerializer(serializers.ModelSerializer):
builds = serializers.PrimaryKeyRelatedField()

class Meta:
model = Depot
fields = ('id', 'name', 'builds', 'depot_type')
read_only_fields = ('id',)

def validate(self, attrs):
build = attrs['builds']
if build == None:
raise serializers.ValidationError("Build could not be found")

for depot in build.depot_set.all():
if depot.name == attrs['name']:
raise serializers.ValidationError("Build already contains a depot \"{}\"".format(depot.name))

return attrs

def restore_object(self, attrs, instance=None):
# existence of the build has already been validated
return Depot(**attrs)

此版本导致在 Depot 期间出现以下错误初始化 称呼:
Exception Type: TypeError
Exception Value:
'builds' is an invalid keyword argument for this function
Exception Location: /webapps/cdp_admin_django/lib/python3.4/site-packages/django/db/models/base.py in __init__, line 417

这似乎表明 Depot 模型无法处理 'builds' 参数,尽管它有一个 'builds' ManyToManyField 成员。

Serializers.py 'restore_object' 版本 2:
def restore_object(self, attrs, instance=None):
# existence of the build has already been validated
build = attrs['builds']

depotObj = Depot(name=attrs['name'], depot_type=attrs['depot_type'])
depotObj.builds.add(build)
return depotObj

这给了我错误:
Exception Type: ValueError
Exception Value:
"<Depot: depot_test4>" needs to have a value for field "depot" before this many-to-many relationship can be used.
Exception Location: /webapps/cdp_admin_django/lib/python3.4/site-packages/django/db/models/fields/related.py in __init__, line 524

经过大量调查,我发现如果在尝试操作该字段之前不保存 MYSQL 条目,ManyToMany 关系会给您带来麻烦。因此,restore_object 版本 3:
def restore_object(self, attrs, instance=None):
# existence of the build has already been validated
build = attrs['builds']

depotObj = Depot(name=attrs['name'], depot_type=attrs['depot_type'])
depotObj.save()
depotObj.builds.add(build)
return depotObj

这确实成功地为此实例创建了表条目,但最终抛出以下错误:
Exception Type: IntegrityError
Exception Value:
(1062, "Duplicate entry '5' for key 'PRIMARY'")
Exception Location: /webapps/cdp_admin_django/lib/python3.4/site-packages/MySQLdb/connections.py in defaulterrorhandler, line 38

此错误发生在 rest_framework/mixins.py 调用 serializer.save(force_insert=True) 期间。看起来它应该强制创建一个新的表条目,大概不同意我之前对 Model.save 的调用。

有谁知道这样的设计的正确方法?我觉得这不可能是表结构的不寻常之处。

2014 年 10 月 20 日编辑:
根据下面的建议,我尝试为我的一个模型编写一个新的 ModelSerializer;大多数情况下,由于这些类型的操作顺序问题,我放弃了使用 ModelSerializer 并通过读取 serializer.data 在 vi​​ews.py 中进行所有数据到对象字段处理。

在 ModelSerializer DID 帮助中有一个 PrimaryKeyRelatedField(many=True)。值得注意的是,我能够使用现有模型创建序列化程序实例并获得正确的 serializer.data。但是,我仍然有问题,restore_object 可以做任何事情,除了创建一个新的模型实例并传递 ManyToManyField 值。如果我将该字段传递给模型的 init 函数,我仍然会收到“TypeError: '[PrimaryKeyRelatedField name]' is an invalid keyword argument for this function”。在 REST 库自己保存模型之前,我仍然无法保存模型。此外,在这种模式下,序列化器使用模型的值填充 serializer.data,而不是数据输入中提供的值。因此,如果您不使用 restore_object 中的 PrimaryKeyRelatedField 的 attrs 值,它将被丢弃。

看来我需要将 ModelSerializer.save 覆盖为某种预保存、应用 ManyToMany 输入和后保存,但我需要 attrs 值,以便当时我可以应用和修改 ManyToManyField。我意识到序列化程序确实有 init_data 字段来查看原始输入,但是在序列化程序用于将数据列表反序列化为新对象列表的情况下,我认为没有办法跟踪哪个serializer.init_data 对应哪个serializer.object。

最佳答案

在您的序列化程序版本 1 中,您不必添加

builds = serializers.PrimaryKeyRelatedField()

因为模型序列化器会为你创建这个。事实上,如果您查看文档示例 ( http://www.django-rest-framework.org/api-guide/relations/ ),您会看到当当前模型存在 FK 'to'(不是 M2M 关系)时,应用了 PrimaryKeyRelatedField。

我会从序列化程序中删除它,然后看看发生了什么。

关于mysql - 使用 ManyToManyField 序列化模型时出现 Django REST 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25128985/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com