Я только столкнулся с той же проблемой, было бы действительно полезно сделать структуру ответа менее привязанной к базовой модели. Вот мое взятие:
Чтения легко
Serializer fields имеет параметр source
, который может принимать пунктирные имена для обхода атрибутов.
class ABSerializer(serializers.ModelSerializer):
class Meta:
model = A
fields = ['name', 'age', 'salary']
salary = serializer.IntegerField(source='b.salary') # this is your related_name
Писать ... официально не поддерживается
ПРОВЕРЯЕМЫЕ данных покажет вложенную структуру, и стандартные методы создания и обновления подавится пытается назначить Dict данных в OneToOneField. Хорошей новостью является то, что вы можете обойти это, переопределяя методы create and update. Вот пример с обновлением:
class ABSerializer(serializers.ModelSerializer):
class Meta:
model = A
fields = ['name', 'age', 'salary']
related_fields = ['b']
salary = serializer.IntegerField(source='b.salary') # this is your related_name
def update(self, instance, validated_data):
# Handle related objects
for related_obj_name in self.Meta.related_fields:
# Validated data will show the nested structure
data = validated_data.pop(related_obj_name)
related_instance = getattr(instance, related_obj_name)
# Same as default update implementation
for attr_name, value in data.items():
setattr(related_instance, attr_name, value)
related_instance.save()
return super(ABSerializer,self).update(instance, validated_data)
Конечно, этот пример очень упрощенно, не производит никакой обработки исключений, и не будет работать с более глубоко вложенными объектами ... но вы получите идею.
Другой вариант
Вы могли бы также create a read-write flavor of SerializerMethodField, который будет рассматривать как геттер и сеттер, однако, что, вероятно, в конечном итоге гораздо более многословен, в конце концов.
Надеюсь, что это поможет!
Я предпочитаю перезаписывать метод обновления и явно принимать проверенные данные, поэтому никакие манипуляции с «автоматическими» ошибками не подразумеваются (конечно, за счет «большего количества кода»). В примере 'instance.b.salary = validated_data.get ('b', {}). Get ('зарплата', '$ 1000000')' – danigosa