#django #django-rest-framework
#django #django-rest-framework
Вопрос:
У меня есть два сериализатора, один для Country и один для моей модели Foo, я хочу сохранить объект, используя внешний ключ для этой модели, но он выдает ошибку всякий раз, когда я пытаюсь выполнить проверку.
У меня есть это
class Actor(TLPWrappedModel, CommentableModel):
label = models.CharField(max_length=56, unique=True)
country_of_origin = models.ForeignKey(Country, on_delete=models.CASCADE)
class FooSerializer(serializers.ModelSerializer):
country_of_origin = CountrySerializer()
class Meta:
model = Actor
fields = [
'id',
'country_of_origin',
'label',
]
class Country(models.Model):
label = models.CharField(max_length=56, unique=True)
iso_code = models.CharField(max_length=3, unique=True)
class CountrySerializer(serializers.ModelSerializer):
class Meta:
model = Country
fields = [
'iso_code',
'label',
]
И это то, что я пытаюсь сделать
serializers = FooSerializer(data={'label': 'Foobar',
'country_of_origin': self.country.id})
serializers.is_valid()
print(serializers.errors)
print(serializers.validated_data)
serializers.save()
Но я получаю эту ошибку {'country_of_origin': {'non_field_errors': [ErrorDetail(string='Invalid data. Expected a dictionary, but got int.', code='invalid')]}}
можно ли использовать идентификатор внешнего ключа для проверки и создания объекта с помощью сериализатора?
Ответ №1:
Мы можем обновить to_represent FooSerializer, чтобы получить желаемый результат
Попробуйте
class FooSerializer(serializers.ModelSerializer):
class Meta:
model = Actor
fields = [
'id',
'country_of_origin',
'label',
]
def to_representation(self, instance):
data = super().to_representation(instance)
data['country_of_origin'] = CountrySerializer(instance.country_of_origin)
return data
serializers = FooSerializer(data={'label': 'Foobar', 'country_of_origin': self.country})
serializers.is_valid(raise_expection=True)
serializers.save()
В этом я обновил код, чтобы назначить self.country
as country_of_origin
. Кроме того, я использую метод raise_expection
in is_valid
. Этот метод вернет ошибки в виде ответа 400.
Комментарии:
1. Это не совсем решает проблему. FooSerializer сериализует объект в json, подобный этому {‘label’: ‘Foobar’, ‘country_of_origin’: 1}, когда я хочу {‘label’: ‘Foobar’: ‘country_of_origin’: {‘label’: ‘usa’}} в качестве примера. Или я что-то недопонимаю?
2. о, я обновил ответ. Пожалуйста, попробуйте это и дайте мне знать, если это решит проблему
Ответ №2:
Попробуйте
class FooSerializer(serializers.ModelSerializer):
class Meta:
model = Actor
fields = [
'id',
'country_of_origin',
'label',
]
Вы можете безопасно отказаться от определения «страны происхождения` в FooSerializer
Комментарии:
1. Является ли единственным способом заставить это работать, сохраняя при этом сериализованный json расширенным, чтобы использовать два разных класса сериализатора?
2. Абсолютно нет! есть и другие способы. Я добавляю другой ответ с другим подходом
Ответ №3:
contry_of_origin будет объектом, и вы передаете для него идентификатор.
Вам нужен вложенный сериализатор? : country_of_origin = CountrySerializer() Для примера, который вы привели, я бы посоветовал вам изменить его на PrimaryKeyRelatedField()
Ваш сериализатор будет выглядеть так:
class FooSerializer(serializers.ModelSerializer):
country_of_origin = serializers.PrimaryKeyRelatedField()
class Meta:
model = Actor
fields = [
'id',
'country_of_origin',
'label',
]
Комментарии:
1. Является ли единственным способом заставить это работать, сохраняя при этом сериализованный json расширенным, чтобы использовать два разных класса сериализатора?
2. Вам не понадобится CountrySerializer, если вы передаете идентификатор в primarykeyrelatedfield . Серализаторы необходимы, только если вы планируете просматривать / создавать / редактировать этот пространственный набор данных (модель)
3. Мне нужно, чтобы CountrySerializer видел фактическое содержимое объекта, когда он сериализуется в json.
4. Я думаю, что есть некоторая путаница с требованием. Давайте обсудим это в чате