Django: не удалось связать вложенный дочерний элемент с родительским - PullRequest
0 голосов
/ 06 мая 2020
• 1000

Вот мой parent_model:

from django.db import models
from django.contrib.auth import get_user_model
User = get_user_model()
from PIL import Image

class Work(models.Model):
    user = models.ForeignKey(User, null=True, on_delete=models.SET_NULL)
    name = models.CharField(max_length=200)
    length = models.IntegerField(null=True)
    width = models.IntegerField(null=True)

    def __str__(self):
        return "{}".format(self.id)

Мой child_model:

from django.db import models
from .model_work import *
from .model_taxes import *
from djmoney.models.fields import MoneyField

class Price(models.Model):
    work = models.OneToOneField(Work, on_delete=models.CASCADE, related_name='price')
    price = MoneyField(max_digits=19, decimal_places=4, default_currency='USD', null=True)
    total = models.IntegerField(null=True)

    def __str__(self):
        return "{}".format(self.price)

Вот мой ParentCreateSerializer:

class WorkCreateSerializer(serializers.ModelSerializer):
    """
    Serializer to create a new Work model in DB
    """
    price = PriceCreateSerializer()

    class Meta:
        model = Work
        fields = [
            'user',
            'price',
            'name',
            'length',
            'width'
        ]

    def create(self, validated_data):
        price_data = validated_data.pop('price')
        work = Work.objects.create(**validated_data)
        price = Price.objects.create(**price_data)
        return work

My ChildCreateSerializer:

class PriceCreateSerializer(serializers.ModelSerializer):
    """
    Serializer to create a new Price when new Work model is created in DB
    """
    # work = WorkDetailsSerializer()
    class Meta:
        model = Price
        fields = [
            'work',
            'price',
            'price_currency',
            'total'
        ]

    def create(self, validated_data):
        work_data = validated_data.pop('work')
        work = Work.objects.create(**work_data)
        price = Price.objects.create(**validated_data)
        return price

Когда я отправляю объект, как показано ниже, создаются и родительский, и дочерний объекты, но я не могу передать дочернему элементу родительский идентификатор в качестве внешнего ключа, поэтому они не связаны.

Я попытался связать сериализатор создания дочернего элемента с сериализатором деталей родительского элемента (строка с комментариями в моем ChildCreateSerializer), но это создает ошибку work = WorkDetailsSerializer() NameError: name 'WorkDetailsSerializer' is not defined.

Из-за к инициализации сериализатора, потому что кажется, что это создает бесконечное l oop, как описано в этом Django: Создание вложенных объектов с обратной связью post.

{
    "user":2,
    "price":
        {
            "price":20,
            "price_currency":"EUR",
            "total":32
        },
    "name":"work 42",
    "length":"50",
    "width":"60",
}

Вот результат:

    {
        "id": 33,
        "user": {
            "id": 2,
            "username": "Max",
            "password": "pbkdf2_sha256$180000$WXTaxmhOOTZF$oTx2i/HoZk+lCxHWsRYGVVZcw3/Sy8Micc4YOfaDRaM="
        },
        "price": null,
        "name": "work 42",
        "length": 50,
        "width": 60
    }

Я заметил, что не использую метод create () дочернего сериализатора.

Кто-нибудь знает, как передать дочернему идентификатору родительский идентификатор в качестве внешнего ключа?

Это сделано в методе create (), и если да, то как я могу получить к нему доступ?

1 Ответ

1 голос
/ 06 мая 2020

Это потому, что вам нужно передать вновь созданный экземпляр Work в сериализатор Price. Это делается с помощью метода create () в вашем WorkCreateSerializer.

class WorkCreateSerializer(serializers.ModelSerializer):
"""
Serializer to create a new Work model in DB
"""

price = PriceCreateSerializer()

class Meta:
    model = Work
    fields = [
        'user',
        'price',
        'name',
        'length',
        'width',
        'height',
        'depth',
        'weight',
        'creation_year',
        'description',
        'unit_system'
    ]

def create(self, validated_data):
    price_data = validated_data.pop('price')
    work = Work.objects.create(**validated_data)
    Price.objects.create(work=work, **price_data)

    return art_piece

Как вы можете видеть в строке ниже, вы создаете новый объект Price, которому вы передаете его поле «работа» ( из модели Price) вновь созданный экземпляр "work" из строки выше.

Этот другой пост тоже хорошо объясняет: аргумент create () после ** должен быть сопоставлением, а не Unicode

Что касается вашей проблемы с доступом к методу create () из PriceCreateSerializer, я не знаю, почему вы не получаете к нему доступ.

Надеюсь, это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...