Создание и сохранение объектов внешнего ключа с использованием 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 для этого.