2015-08-07 5 views
4

Так что я follwoing модели:Джанго рамки остальное один в один отношение

class A(models.Model): 
    name = models.CharField() 
    age = models.SmallIntergerField() 

class B(models.Model): 
    a = models.OneToOneField(A) 
    salary = model.IntergerField() 

Теперь я хочу, чтобы создать одну покоя конечную точку там два, как они один к одному. Поэтому я хочу следовать как получить

{ 
    url: 'http://localhost/customs/1/', 
    name: 'abc', 
    age: 24, 
    salary: 10000 
} 

Similary, я также хочу создать записи и обновить. Пожалуйста, дайте мне знать, как я могу достичь этого в каркасе отдыха django.

ответ

8

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

Чтения легко

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, который будет рассматривать как геттер и сеттер, однако, что, вероятно, в конечном итоге гораздо более многословен, в конце концов.

Надеюсь, что это поможет!

+0

Я предпочитаю перезаписывать метод обновления и явно принимать проверенные данные, поэтому никакие манипуляции с «автоматическими» ошибками не подразумеваются (конечно, за счет «большего количества кода»). В примере 'instance.b.salary = validated_data.get ('b', {}). Get ('зарплата', '$ 1000000')' – danigosa

Смежные вопросы