2015-11-02 5 views
0

Я пробовал несколько решений, размещенных в других местах для этой проблемы, но не повезло. Похоже, он не поддерживается в DRF. У кого-нибудь есть предложения по тому, как это сделать?Django rest framework вложенной сериализатор с собственными ссылочными объектами

У меня есть модель reports и модель section. Раздел определяется следующим образом:

class Section(models.Model): 
    title = models.CharField(max_length=255) 
    report = models.ForeignKey(Report) 
    order = models.PositiveIntegerField() 
    section = models.ForeignKey('self', related_name='section_section', blank=True, null=True) 
    content = models.TextField(blank=True) 

Я хочу, чтобы отобразить его данные как и по сообщениям:

[ 
    { 
     "id": 1, 
     "title": "test", 
     "subtitle": "test", 
     "section_set": [ 
      { 
       "id": 1, 
       "title": "test", 
       "report": 1, 
       "order": 1, 
       "section_set": [ 
        { 
         "id": 1, 
         "title": "test", 
         "report": 1, 
         "order": 1, 
         "section": null, 
         "content": "<p>test</p>" 
        }, 
        { 
         "id": 2, 
         "title": "test", 
         "report": 1, 
         "order": 1, 
         "section": 2, 
         "content": "<p>test</p>" 
        }, 
        { 
         "id": 3, 
         "title": "test", 
         "report": 1, 
         "order": 1, 
         "section": null, 
         "content": "<p>test</p>" 
        } 
       ], 
       "content": "<p>test</p>" 
      }, 
      { 
       "id": 2, 
       "title": "test", 
       "report": 1, 
       "order": 1, 
       "section": 2, 
       "content": "<p>test</p>" 
      }, 
      { 
       "id": 3, 
       "title": "test", 
       "report": 1, 
       "order": 1, 
       "section": null, 
       "content": "<p>test</p>" 
      } 
     ] 
    } 
] 

Моя текущая (попытка) реализация выглядит следующим образом:

class SubsectionSerializer(serializers.ModelSerializer): 
class Meta: 
    model = Section 


class SectionSerializer(serializers.ModelSerializer): 
    section = SubsectionSerializer() 

    class Meta: 
     model = Section 
     fields = ('id', 'title', 'report', 'order', 'section', 'content') 


class CountryReportSerializer(serializers.ModelSerializer): 
    section_set = SectionSerializer(many=True) 

    class Meta: 
     model = CountryReport 
     fields = ('id', 'title', 'subtitle', 'section_set') 


class MapsSerializer(serializers.ModelSerializer): 
    class Meta: 
     model = Map 
     fields = ('id', 'country', 'map_image', 'report') 

но результат выглядит следующим образом:

{ 
    "id": 1, 
    "title": "test", 
    "subtitle": "test", 
    "section_set": [ 
     { 
      "id": 1, 
      "title": "Section 1", 
      "report": 1, 
      "order": 1, 
      "section": null, 
      "content": "<p>test</p>" 
     }, 
     { 
      "id": 2, 
      "title": "Section 2", 
      "report": 1, 
      "order": 1, 
      "section": null, 
      "content": "<p>test</p>" 
     }, 
     { 
      "id": 3, 
      "title": "Subsection 1", 
      "report": 1, 
      "order": 1, 
      "section": { 
       "id": 1, 
       "title": "Section 1", 
       "order": 1, 
       "content": "<p>test</p>", 
       "report": 1, 
       "section": null 
      }, 
      "content": "<p>test</p>" 
     } 
    ] 
} 
+0

Вы читали DRF документы на вложенные представления? [Это] (http://www.django-rest-framework.org/api-guide/serializers/#dealing-with-nested-objects) или [это] (http: //www.django-rest-framework. орг/апите-гид/сериализаторы/# указание вложенной-сериализация). – Ivan

+0

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

+1

Структура, которую вы хотите, недействительна JSON – rednaw

ответ

1

То, как вы определяете подразделение, не связывает его с полем вашего поля, как показывает ошибка. Вы пробовали определение вашего сериалайзера просто так:

class SectionSerializer(serializers.ModelSerializer): 
    class Meta: 
     model = Section 

Поскольку секция имеет FK раздел, он должен быть возвращен как можно было бы ожидать от сериализатора.

Для того, чтобы результаты JSON, возвращаемые в этом сериализатором содержать вложенные объекты JSON, а не только FKS, есть два пути, вы можете взять с собой:

1) depth=

class SectionSerializer(serializers.ModelSerializer): 
    class Meta: 
     model = Section 
     depth=2 

Это будет следовать FKs вниз, создавая объекты JSON по мере того, как он идет на указанную вами глубину.

2) Определить SubSerializer обрабатывать создание объекта JSON:

class SubsectionSerializer(serializers.ModelSerializer): 
    class Meta: 
     model = Section 

class SectionSerializer(serializers.ModelSerializer): 
    section = serializers.SubsectionSerializer() 
    class Meta: 
     model = Section 
     fields = ('id', 'title', 'report', 'order', 'section', 'content') 

------------------------ EDIT-- -------------------------

для ясности, возможно, имеет смысл переименовать соответствующий раздел биты модели:

class Section(models.Model): 
    title = models.CharField(max_length=255) 
    report = models.ForeignKey(Report) 
    order = models.PositiveIntegerField() 
    parent_section = models.ForeignKey('self', related_name='child_sections', blank=True, null=True) 
    content = models.TextField(blank=True) 

С новыми именами вы можете использовать следующий сериализатор:

class SectionSerializer(serializers.ModelSerializer): 
    child_sections = serializers.SubsectionSerializer(many=True) 
    class Meta: 
     model = Section 
     fields = ('id', 'title', 'report', 'order', 'child_sections', 'content') 
+0

Это было одно из решений, предложенных в другом вопросе. Он работает только с мета, определенной вами, как вы предполагали, но я бы хотел, чтобы они вложены друг в друга соответствующим образом. –

+1

@Wilson - вы говорите, что проблема в том, что с этим решением вы видите только FK вместо реальных объектов JSON раздела? –

+0

Я обновил свой вопрос с текущим выходом. В принципе, я получаю все объекты раздела, относящиеся к отчету на одном уровне. Тем не менее, я хотел бы, чтобы объекты разделов были вложены под eachother, поскольку они являются подразделами. Сейчас он ровный. –

1

Понял работает следующим раствором:

class RecursiveField(serializers.Serializer): 
    def to_representation(self, value): 
     serializer = self.parent.parent.__class__(value, context=self.context) 
     return serializer.data 


class SectionSerializer(serializers.ModelSerializer): 
    children = RecursiveField(many=True) 

    class Meta: 
     model = Section 
     fields = ('id', 'order', 'title', 'content', 'parent', 'children') 


class CountryReportSerializer(serializers.ModelSerializer): 
    section_set = serializers.SerializerMethodField('get_parent_sections') 

    @staticmethod 
    def get_parent_sections(self, obj): 
     parent_sections = Section.objects.get(parent=None, pk=obj.pk) 
     serializer = SectionSerializer(parent_sections) 
     return serializer.data 

    class Meta: 
     model = CountryReport 
     fields = ('id', 'title', 'subtitle', 'section_set') 


class MapsSerializer(serializers.ModelSerializer): 
    class Meta: 
     model = Map 
     fields = ('id', 'country', 'map_image', 'report') 
0

метод ПОЦЕЛУЙ, RecursiveField сериализации просто возвращают значения

class RecursiveField(serializers.ModelSerializer): 
    def to_representation(self, value): 
     serializer_data = TypeSerializer(value, context=context).data 
     return serializer_data 
    class Meta: 
      model = Type 
      fields = '__all__' 

class TypeSerializer(serializers.ModelSerializer): 
    extends_type = RecursiveField(allow_null=True) 

    class Meta: 
     model = Type 
     fields = '__all__' 

в модели.ру

class Type(models.Model): 
    id = models.AutoField(primary_key=True) 
    extends_type = models.ForeignKey('self', models.SET_NULL, null=True) 

вы можете ввести в петлю легко, чтобы избежать этого, мы можем скопировать TypeSerializer в SubTypeSerializer и сосчитать или управлять глубиной с по ключевым прилавка в контексте под

def to_representation(self, value): 
    lvalue = context.get('count', 0) 
    lvalue += 1 
    context.update({'count': lvalue}) 
    serializer_data = SubTypeSerializer(value, context=context).data 
    return serializer_data 

class TypeSerializer(serializers.ModelSerializer): 
    extends_type = RecursiveField(allow_null=True) 
    def to_representation(self, instance): 
     self.context.update({'count': 0}) 
     return super().to_representation(instance) 

    class Meta: 
     model = Type 
     fields = '__all__' 

class SubTypeSerializer(serializers.ModelSerializer): 
    extends_type = RecursiveField(allow_null=True) 

    class Meta: 
     model = Type 
     fields = '__all__' 
Смежные вопросы