Django RestFramework组由

时间:2015-06-26 11:10:30

标签: json xml django django-rest-framework

我的问题与Django RestFramework有关,关于如何对元素进行分组。

这是我的 serializers.py

from collaborativeAPP.models import *
from rest_framework import serializers

class VocabSerializer(serializers.ModelSerializer):
        term_word = serializers.CharField(source='term.word',read_only=True)
        kwdGroup = serializers.StringRelatedField()
        class Meta:
        model = Vocab
                fields = ('id','term_word', 'meaning','kwdGroup')

class TermSerializer(serializers.ModelSerializer):

        word = serializers.CharField(read_only=True)
        class Meta:
                model = Term
                fields = ('url', 'word')

以下json是实际结果:

{"results":[
            {
                "id": 5,
                "term_word": "word1",
                "meaning": "Text1"
                "kwdGroup": "A"
            },
            {
                "id": 6,
                "term_word": "word2",
                "meaning": "Text2"
                "kwdGroup": "A"
            },
            {
                "id": 7,
                "term_word": "word3",
                "meaning": "Text3"
                "kwdGroup": "A"
            }
        ]}

你可以注意到“kwdGroup”是一个重复的元素,我要分组。

我想按照kwdGroup分组

{"A":[
       {
        "id": 5,
        "term_word": "word1",
        "meaning": "Text1"
        },
        {
        "id": 6,
        "term_word": "word2",
        "meaning": "Text2"
        },
        {
        "id": 7,
        "term_word": "word3",
        "meaning": "Text3"
        }
    ]
}

我正在寻找关于api指南的http://www.django-rest-framework.org/的答案,但我很难找到一种方法来引导它。 你有同样的问题吗?你有什么建议我怎么办?你有任何使用Django RestFramework处理元素分组的例子吗?

提前致谢。

3 个答案:

答案 0 :(得分:3)

实现此目的的一种方法是使用SerializerMethodField。以下可能与您的使用情况略有不同,但您可以采用相应的方法。还有其他方法可以实现这一点,包括覆盖to_representation方法,但它们依赖于混乱DRF的内部工作而不是相关的。

models.py

class Dictionary(Model):
    id = PrimaryKey


class Word(Model):
    dictionary = ForeignKey(Dictionary, related_name='words')
    word = Charfield()
    group = Charfield()

serializers.py

class WordSerializer(serializers.ModelSerializer):
    word = serializers.CharField(read_only=True)

    class Meta:
            model = Word
            fields = ('word',)


class DictionarySerializer(serializers.ModelSerializer):
    group_a = serializers.SerializerMethodField()
    group_b = serializers.SerializerMethodField()

    def get_group_a(self, instance):
        return WordSerializer(instance.words.filter(group='a'), many=True).data

    def get_group_b(self, instance):
        return WordSerializer(instance.words.filter(group='b'), many=True).data

    class Meta:
        model = Dictionary
        fields = ('group_a', 'group_b')

一个例子

>>> my_dictionary = Dictionary.objects.create()
>>> Word.objects.bulk_create(
        Word(word='arrow', group='a' dictionary=my_dictionary),
        Word(word='apple', group='a' dictionary=my_dictionary),
        Word(word='baby', group='b' dictionary=my_dictionary),
        Word(word='banana', group='b' dictionary=my_dictionary)
)
>>> serializer = DictionarySerializer(my_dictionary)
>>> print serializer.data
{
    'group_a': {
        'word': 'arrow',
        'word': 'apple'
    },
    'group_b': {
        'word': 'baby',
        'word': 'banana'
    },
}

答案 1 :(得分:3)

我们假设kwdGroup字段是名为KeyWordGroup的模型的关系字段。

默认ListSerializer使用to_representation方法呈现序列化对象rest_framework的列表:

class ListSerializer(BaseSerializer):
     ...

    def to_representation(self, data):
        """
          List of object instances -> List of dicts of primitive datatypes.
        """
        # Dealing with nested relationships, data can be a Manager,
        # so, first get a queryset from the Manager if needed
        iterable = data.all() if isinstance(data, models.Manager) else data

        return [
            self.child.to_representation(item) for item in iterable
        ]

我们可以修改ListSerializer以对结果进行分组,例如:

class VocabListSerializer(serializers.ListSerializer):

     def to_representation(self, data):

         iterable = data.all() if isinstance(data, models.Manager) else data

         return {
                  kwdGroup: super().to_representation(Vocab.objects.filter(kwdGroup=kwdGroup))
                  for kwdGroup in KeyWordGroup.objects.all()
                }

然后,我们可以将修改后的VocabListSerializerVocabSerializer一起使用。

class VocabSerializer(serializers.Serializer):
...
    class Meta:
        list_serializer_class = VocabListSerializer

答案 2 :(得分:-2)

您可以使用“序列化关系”,尤其是“嵌套关系”。请参阅文档here