Django-Rest框架:通过ModelVi创建对象时按ID指定OneToOneField

2024-06-01 05:56:04 发布

您现在位置:Python中文网/ 问答频道 /正文

我在创建一个带有按ID的OneToOneField引用的对象时遇到一些问题。我的代码示例:

在模型.py在

class Person(models.Model):
    name = models.CharField(length=50)


class ExtraInfo(models.Model):
    person = models.OneToOneField(
        Person,
        related_name='+',
        primary_key=True,
        on_delete=models.CASCADE
    )
    info = models.CharField(length=50)

在序列化程序.py在

^{pr2}$

在视图.py在

class ExtraInfoView(viewsets.ModelViewSet):
    queryset = models.ExtraInfo.objects.all()
    serializer_class = serializers.ExtraInfoSerializer

在网址.py在

...
api_router = DefaultRouter()
api_router.register(r'extrainfo', ExtraInfoView)

url_patterns = [
    url(r'/', include(api_router.urls))
]
...

现在,每当我执行GET/extrainfo/操作时,都会得到以下内容:

{
    "count": 2,
    "next": null,
    "previous": null,
    "results": [
        {
            "person": 1,
            "info": "foo"
        },
        {
            "person": 2,
            "info": "bar"
        }
    ]
}

所以这一切都很好-正是我所期望的。当我试图创建一些ExtraInfo时,当我发布到/ExtraInfo/时,问题就出现了,比如:

{
    "person": 3,
    "info": "blah"
}

我得到以下错误:

ValueError: Cannot assign "3": "ExtraInfo.person" must be a "Person" instance.

所以我明白它的意思-如果我用定制代码来做这个,我会想做一些类似的事情ExtraInfo.objects.create(person_id=3,info=“blah”)。我就是不知道怎么让它表现得像我想要的那样。在

我看了一眼this answer,我想不出哪里出了问题。我似乎可以通过在序列化程序中添加以下内容来解决此问题:

def create(self, validated_data):
    validated_data['person_id'] = validated_data['person']
    del validated_data['person']
    return super(ExtraInfoSerializer, self).create(validated_data)

但这似乎不是最好的办法。我觉得我要么错过了一些小的东西,要么根本上误解了一些东西,但不管怎样,我觉得奇怪的是,它会序列化到GET的主键,但不会在POST中使用它。任何帮助都将不胜感激。在


Tags: 代码pyinfoapidata序列化modelscreate
1条回答
网友
1楼 · 发布于 2024-06-01 05:56:04

序列化程序希望person是模型实例,因此可以执行以下操作:

{
    "person": Person.objects.get(pk=3),
    "info": "blah"
}

在这个视图中,您可以得到相关模型实例的一阶表示,这是它的主键。您还可以通过在序列化程序中指定depth参数来获得完整的模型实例。比如:

^{pr2}$

相关问题 更多 >