Я создаю Rest Api, который читает и обновляет модель под названием Requirements.Я использую ModelSerializer.Модель Requirements имеет внешний ключ для модели Materials.
Проблема в том, что мой пользователь API не знает внутренний идентификатор материалов. Он знает только код, уникальный для материала.Теперь идея состоит в том, что в PUT он передает мне код материала, и я устанавливаю идентификатор материала, а в GET он получает код материала, основанный на внешнем ключе материала Требований
. Мне удалось заставить работать PUT, переопределивметод проверки и объявления:
material_code = serializers.CharField(max_length=50);
Это код, указанный в конце поста.Обратите внимание, что это фрагмент всего сложного кода.В полном коде сериализатор требований вложен в другой сериализатор, который вложен в другой сериализатор.Но я не думаю, что это имеет отношение к проблеме.
Тогда мне удается заставить GET работать, используя настраиваемую опцию источника в поле material_code, где источником является свойство в моей модели требований.Для этого объявление должно быть изменено на:
material_code = serializers.ReadOnlyField(source='get_material_code')
По некоторым причинам оба:
material_code = serializers.Field()
и
material_code = serializers.Field(source='get_material_code')
ведут себя странным образом и неработать либо с PUT, либо с GET, вызывая исключение «Field.to_internal_value () должно быть реализовано».Я попытался реализовать to_internal_value и попробовать, но не получилось.И в конце концов, material_code не должен переходить к внутреннему значению.Как только мне удалось установить идентификатор материала, он мне не нужен.
Нет способа заставить одновременно работать PUT и GET.GET будет работать только с сериализаторами. ReadOnlyField и PUT с сериализаторами. CharField.
Использование PUT с serializers.ReadOnlyField создает тип исключения: KeyError Значение исключения 'material_code'.
Использование GET с serializers.CharField создает тип исключения: AttributeError Значение исключения: Got AttributeError при попытке получить ошибкузначение для поля material_code
на сериализаторе RequirementsSerializer
.Поле сериализатора может иметь неправильное имя и не соответствовать ни одному атрибуту или ключу в экземпляре Requirements
.Исходный текст исключения был: объект «Требования» не имеет атрибута «материал_код».
Возможно, весь подход неверен.Мне нужен перевод между внешне видимым кодом и внутренним идентификатором.Это не должно быть так сложно.Это мой первый проект на Python, и, возможно, есть встроенный способ заставить его работать в Django Rest Api, но я не смог найти его в документации.
Буду очень признателен за любую помощь.Кстати, это мой первый пост stackoverflow.Если я сделал что-то не так, пожалуйста, дайте мне знать.
class Materials (models.Model):
class Meta:
db_table = 'materials'
code = models.CharField(max_length=50);
full_name = models.CharField(max_length=50);
def __str__(self):
return self.full_name
class Requirements (models.Model):
class Meta:
db_table = 'requirements'
material = models.ForeignKey(Materials, on_delete=models.CASCADE)
acceptance_method = models.CharField(max_length=4)
@property
def get_material_code(self):
return self.material.code
class RequirementsSerializer(serializers.ModelSerializer):
material_code = serializers.CharField(max_length=50);
material = serializers.HiddenField(default=1)
class Meta:
model = Requirements
fields = [ 'id',
'material' ,
'material_code' ,
'acceptance_method'
]
read_only_fields = ['material']
def validate(self, data):
# Fill material with a pk on Materials models
# This is necessary since the API receive a material code instead of the model id
if Materials.objects.filter(code = data['material_code']).exists() :
data['material'] = Materials.objects.get(code = data['material_code'])
else:
raise serializers.ValidationError('Material '+ data['material_code'] + ' does not exists')
return data