Создание и сохранение объектов внешнего ключа с использованием SlugRelatedField

Я только что начал с рамки Django REST, и у меня возникли проблемы с сохранением внешних ключей. У меня есть модель Merchant и модель Phone. Phone имеет внешний ключ для Merchant. При создании запроса POST на Merchant я хочу создать объекты Phone для чисел, указанных в запросе. Но когда я предоставляю номера телефонов, это дает мне следующую ошибку:

Объект с телефоном = 0123456789 не существует.

Я просто хочу, чтобы он создал сам объект Phone. Вот модели, которые я использую:

class Merchant(models.Model):
    merchant_id       = models.CharField(max_length=255)
    name              = models.CharField(max_length=255)
    is_active         = models.BooleanField(default=True)

    class Meta:
        managed = True
        db_table = 'merchant'

    # Managers
    objects = models.Manager()
    active = managers.ActiveManager()

class Phone(models.Model):
    phone      = models.CharField(max_length=255)
    merchant   = models.ForeignKey('merchant.Merchant',
                                    related_name='phones',
                                    blank=True,
                                    null=True)

    class Meta:
        managed = True
        db_table = 'phone'

И вот представление и сериализатор, которые я использую с помощью

class MerchantSerializer(serializers.ModelSerializer):
    phones = serializers.SlugRelatedField(
        many=True,
        slug_field='phone',
        queryset=primitives.Phone.objects.all())

    class Meta:
        model = Merchant
        fields = (
            'merchant_id',
            'name',
            'is_active',
            'phones',
        )

class MerchantViewSet(viewsets.ModelViewSet):
    queryset = Merchant.active.all()
    serializer_class = MerchantSerializer

Вот что выглядит мое тело запроса:

{
    "merchant_id": "emp011",
    "name": "Abhinav",
    "is_active": true,
    "phones": [
        "0123456789",
        "9876543210"
    ]
}

Здесь ответ:

400 Bad Request

{"phones":["Object with phone=0123456789 does not exist."]}

Ответ 1

SlugRelatedField, предоставляемый инфраструктурой Django REST, как и многие связанные с ним поля, предназначен для использования с уже существующими объектами. Поскольку вы ищете ссылки на объекты, которые уже существуют, или объект, который нужно создать, вы не сможете использовать его как есть.

Вам понадобится пользовательский SlugRelatedField, который создаст новый объект, если он не существует.

class CreatableSlugRelatedField(serializers.SlugRelatedField):

    def to_internal_value(self, data):
        try:
            return self.get_queryset().get_or_create(**{self.slug_field: data})[0]
        except ObjectDoesNotExist:
            self.fail('does_not_exist', slug_name=self.slug_field, value=smart_text(data))
        except (TypeError, ValueError):
            self.fail('invalid')

class MerchantSerializer(serializers.ModelSerializer):
    phones = CreateableSlugRelatedField(
        many=True,
        slug_field='phone',
        queryset=primitives.Phone.objects.all()
    )

    class Meta:
        model = Merchant
        fields = (
            'merchant_id',
            'name',
            'is_active',
            'phones',
        )

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

Ответ 2

Вы должны указать значение для поля телефона объекта Phone. Если вы хотите создать объект телефона без указания значения для полевого телефона, вам нужно включить пустые и пустые поля.

phone = models.CharField(max_length=255,null=true,blank=true)

Если у вас по-прежнему возникают проблемы, убедитесь, что данные сообщения содержат необходимые поля. Вы можете использовать ipdb для этого.