如何自动创建foreingKey对象(python和django)

ru9i0ody  于 2023-03-09  发布在  Go
关注(0)|答案(2)|浏览(98)

我在创建一个简单的REST API
这是我从设备中得到的实际结果,我首先创建组和选项,然后进行关联,但我希望在创建设备的同时创建选项。
我现在的设备结果

[
   
    {
        "id_device": "a099d2ce-812b-4d85-8c8b-cfe71057fbe7",
        "group": {
            "id_group": "39407ef6-1a3e-4965-9b61-96f6c40b76b3",
            "name": "Cozinha"
        },
        "options": [
            {
                "id_option": "1b383a37-5229-4ae0-9649-f76aa32eeda0",
                "name": "1",
                "identifier": "POWER1"
            },
            {
                "id_option": "4ff5406a-8c7b-4517-9ec0-14fd4f68f30b",
                "name": "2",
                "identifier": "POWER2"
            },
            {
                "id_option": "a541216d-f509-4461-85ca-444491ac9217",
                "name": "3",
                "identifier": "POWER3"
            },
            {
                "id_option": "3debe828-edd6-4d83-bfd8-2776a1594380",
                "name": "4",
                "identifier": "POWER4"
            }
        ],
        "name": "Interruptor 4",
        "identifier": "identifiertest"
    },
]

我的models.py

from uuid import uuid4
from django.db import models

class Options(models.Model):
    id_option = models.UUIDField(primary_key=True, default=uuid4, editable=False)
    name = models.CharField(max_length=255)
    identifier = models.CharField(max_length=255)

    class Meta:
        ordering = ['name']

    def __str__(self):
        return self.name

class Groups(models.Model):
    id_group = models.UUIDField(primary_key=True, default=uuid4, editable=False)
    name = models.CharField(max_length=255)

    class Meta:
        ordering = ['name']

    def __str__(self):
        return self.name

class Devices(models.Model):
    id_device = models.UUIDField(primary_key=True, default=uuid4, editable=False)
    name = models.CharField(max_length=255)
    identifier = models.CharField(max_length=255)
    options = models.ManyToManyField(Options)
    group = models.ForeignKey(Groups, on_delete=models.CASCADE, default="")

视图集

from rest_framework import viewsets
from devices.api import serializers
from devices import models

class DevicesViewsets(viewsets.ModelViewSet):
    serializer_class = serializers.DevicesSerializer
    queryset = models.Devices.objects.all()
    
class OptionsViewsets(viewsets.ModelViewSet):
    serializer_class = serializers.OptionsSerializer
    queryset = models.Options.objects.all()

class GroupsViewsets(viewsets.ModelViewSet):
    serializer_class = serializers.GroupsSerializer
    queryset = models.Groups.objects.all()

串化器

from rest_framework import serializers
from devices import models

class OptionsSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Options
        fields = '__all__'

class GroupsSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Groups
        fields = '__all__'

class DevicesSerializer(serializers.ModelSerializer):
    group = GroupsSerializer()
    options = OptionsSerializer(many=True)

    class Meta:
        model = models.Devices
        fields = '__all__'

我发送此消息以创建设备

{
    "group": {
        "name": "newgroup"
    },
    "options": [
        {    
           "name": "teste1",
           "identifier": "teste1" 
        }
     ],
    "name": "teste1",
    "identifier": "teste1"
}

但得到这个错误:
/devices/处的AssertionError默认情况下,.create()方法不支持可写嵌套字段。请为序列化程序devices.api.serializers.DevicesSerializer编写显式.create()方法,或在嵌套序列化程序字段上设置read_only=True。请求方法:POST请求URL:http://127.0.0.1:8000/devices/ Django版本:4.1.7异常类型:Assert错误异常值:
默认情况下,.create()方法不支持可写嵌套字段。请为序列化程序devices.api.serializers.DevicesSerializer编写显式.create()方法,或在嵌套序列化程序字段上设置read_only=True
我知道答案在这里,但我不知道如何做到这一点。我尝试了一些解决方案,从互联网上,但没有成功,所以有人能帮助我吗?

qybjjes1

qybjjes11#

序列化器.py

class DevicesSerializer(serializers.ModelSerializer):
    group = GroupsSerializer()
    options = OptionsSerializer(many=True)

    class Meta:
        model = models.Devices
        fields = '__all__'

    def create(self, validated_data):
        group_data = validated_data.pop('group')
        options_data = validated_data.pop('options')
        group, _ = models.Groups.objects.get_or_create(**group_data)
        options = [models.Options.objects.create(**option_data) for option_data in options_data]
        device = models.Devices.objects.create(group=group, **validated_data)
        device.options.set(options)
        return device

视图集.py:

from rest_framework import viewsets
from devices.api import serializers
from devices import models

class DevicesViewsets(viewsets.ModelViewSet):
    serializer_class = serializers.DevicesSerializer
    queryset = models.Devices.objects.all()

    def perform_create(self, serializer):
        serializer.save()

    
class OptionsViewsets(viewsets.ModelViewSet):
    serializer_class = serializers.OptionsSerializer
    queryset = models.Options.objects.all()

class GroupsViewsets(viewsets.ModelViewSet):
    serializer_class = serializers.GroupsSerializer
    queryset = models.Groups.objects.all()
vi4fp9gy

vi4fp9gy2#

你是对的,答案就在那里。基本上你必须为你的DevicesSerializer类提供一个def create(self, validated_data)方法。
以下是一些可能有所帮助的信息:

class DevicesSerializer(serializers.ModelSerializer):
    group = GroupsSerializer()
    options = OptionsSerializer(many=True)

    class Meta:
        model = models.Devices
        fields = '__all__'

    def create(self, validated_data):
        options_data = validated_data.pop("options")
        device = models.Devices.objects.create(**validated_data)  # or you can manually pass the fields/data as kwargs

        for option_data in options_data:
            models.Options.objects.create(device=device, **option_data)

        return device

基本上,您需要手动保存基本对象(Device),然后手动迭代选项数据,并创建指向新创建的device的每个选项。

相关问题