2014-05-16 3 views
0

Вот сценарий:Сериализация нескольких моделей в одном виде

У меня есть две модели; FileObj и DirObj.

class DirObj(models.Model): 
    [...] 
    parent = models.ForeignKey('self') 
    [...] 

class FileObj(models.Model): 
    [...] 
    parent = models.ForeignKey(DirObj) 
    [...] 

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

class FileObjSerializer(serializers.ModelSerializer): 
    [...] 
    class Meta: 
     model = FileObj 

class DirObjSerializer(serializers.HyperlinkedModelSerializer): 
    [...] 
    parent = serializers.HyperlinkedRelatedField(
     view_name = 'dirobj-detail') 
    class Meta: 
     model = DirObj 

И давайте говорить, что, когда пользователь переходит на «/ директории/[dir_id]» Я хочу, чтобы вернуть файл и содержимое каталогов DirObj, заданный «dir_id» в одном представлении, который использует два разных сериализатора. Сейчас у меня есть (не точно, но достаточно, чтобы вы получите суть близко) следующее:

class DirContents(generics.GenericAPIView): 
    def get(self, request, *args, **kwargs): 
     files = FileObj.objects.filter(parent = kwargs.get('dir_id')) 
     dirs = DirObj.objects.filter(parent = kwargs.get('dir_id')) 
     files_serializer = FileObjSerializer(files, many = True) 
     dirs_serializer = DirObjSerializer(dirs, many = True) 
     response = files_serializer.data + dirs_serializer.data 
     return Response(response) 

Это чувствует, как уродливые взломать. Он также игнорирует любые гиперссылки, которые обычно отображались при просмотре API (т. Е. ГиперссылкиRelatedFields не отображаются в виде гиперссылок, как они должны.) Есть ли способ сериализации произвольного количества моделей и возврата их в одном представлении без нарушая API-интерфейс, доступный для просмотра, и/или должен сделать (что я предполагаю) кучу дополнительной работы, чтобы заставить гиперссылку работать правильно?

Заранее благодарен!

ответ

3

вопроса вы столкнулись с текущим кодом, в частности, с ссылкой не работает, потому что вы не passing in any context к сериализатору.

class DirContents(generics.GenericAPIView): 
    def get(self, request, *args, **kwargs): 
     files = FileObj.objects.filter(parent=kwargs.get('dir_id')) 
     dirs = DirObj.objects.filter(parent=kwargs.get('dir_id')) 

     context = { 
      "request": request, 
     } 

     files_serializer = FileObjSerializer(files, many=True, context=context) 
     dirs_serializer = DirObjSerializer(dirs, many=True, context=context) 

     response = files_serializer.data + dirs_serializer.data 

     return Response(response) 

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

Для тех, кто приезжает сюда, чтобы объединить две модели в один сериализатор:

Там нет простого способа поддерживать несколько различные модели в одном представлении, когда используются общие взгляды. Похоже, что вы не используете их для фильтрации запросов, но это действительно возможно, хотя и не таким образом, что это будет считаться «чистым» любым способом.

class DirContents(generics.GenericAPIView): 
    def get(self, request, *args, **kwargs): 
     files = FileObj.objects.filter(parent=kwargs.get('dir_id')) 
     dirs = DirObj.objects.filter(parent=kwargs.get('dir_id')) 

     files_list = list(files) 
     dirs_list = list(dirs) 

     combined = files_list + dirs_list 

     serializer = YourCombinedSerializer(combined, many=True) 

     return Response(serializer.data) 
+0

Передача в контексте действительно фиксировала гиперссылку. Я продолжу искать чистый способ сериализации моделей, но ваш ответ в значительной степени отвечает на мой вопрос (и дает мне немного больше, чтобы читать дальше.) Спасибо! – musashiXXX

0

Добавить файлы в DirObjSerializer как плавающее поле с опцией many=True. Для получения дополнительной информации: http://www.django-rest-framework.org/api-guide/relations

class DirObj(models.Model): 
    [...] 
    parent = models.ForeignKey('self') 
    [...] 

class FileObj(models.Model): 
    [...] 
    parent = models.ForeignKey(DirObj, related_name='files') 
    [...] 


class FileObjSerializer(serializers.ModelSerializer): 
    [...] 
    class Meta: 
     model = FileObj 

class DirObjSerializer(serializers.HyperlinkedModelSerializer): 
    [...] 
    parent = serializers.HyperlinkedRelatedField(
     view_name = 'dirobj-detail') 
    files = serializers.HyperlinkedRelatedField(many=True, 
     view_name = 'fileobj-detail') 

    class Meta: 
     model = DirObj 
+0

Несомненно, но это возвращает FileObjs как вложенные элементы. Я не хочу, чтобы они были вложенными; Мне нужно, чтобы они были отдельными сущностями. Кроме того, у DirObj уже есть связанное поле с полем «родительский» в FileObj. В этом примере эта связанная область будет называться «fileobj». – musashiXXX

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