2015-06-26 16 views
6

Mein Problem bezieht sich auf Django RestFramework und beschreibt, wie Elemente gruppiert werden.Django RestFramework-Gruppe von

Das ist mein 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') 

Die folgende json es das tatsächliche Ergebnis ist:

{"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" 
      } 
     ]} 

Wie Sie feststellen können "kwdGroup" ist ein sich wiederholendes Element, das ich-Gruppe, die .

würde ich zu einer Gruppe wie von kwdGroup

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

Ich bin für Antworten auf http://www.django-rest-framework.org/ auf api Führung suchen, aber ich habe Schwierigkeiten, einen Ansatz zu führen, mit ihm zu finden. Teilen Sie das gleiche Problem? Hast du einen Vorschlag wie kann ich das machen? Haben Sie ein Beispiel, das sich mit der Gruppierung von Elementen mit Django RestFramework befasst?

Vielen Dank im Voraus.

+3

Wie erhalten Sie Ihr "tatsächliches" Ergebnis? Fügen Sie den Code der Ansicht oder eine Abfrage, die Sie verwenden, um die Daten –

+0

Sylvain, für meine Frage, die Sie brauchen, um den Code nicht zu bewerten. Wenn Sie das django RestFramework kennen, müssen Sie nur wissen, ob DjangoRestFrameWork diese Fähigkeit bietet oder nicht. Es gibt mehrere Skripte, die zum Erstellen dieses JSON beitragen (serializer.py, models.py, views.py, urls).py) und es macht keinen Sinn, sie alle zu zeigen. Was ich zeigen kann, ist der Serializer, der jetzt aktualisiert wird. – ePascoal

+0

Ich bin kürzlich in dasselbe Problem geraten. Ich habe nur den Serializer gemieden und die Methode get der Methode übersprungen, die JSON-Ausgabe direkt zu erzeugen. Ich würde gerne wissen, ob es einen Weg gibt, es ordentlich mit Serialisierern zu machen. Ich hatte eigentlich 2 Ebenen der Gruppierung zu tun. –

Antwort

0

Sie könnten "Serializer-Beziehungen" und insbesondere "verschachtelte Beziehungen" verwenden. Siehe Dokumentation here

+0

Dies löst nicht das Problem im Zusammenhang mit Gruppierungselementen in einem übergeordneten Element nach einem Gruppentyp. – Falcoa

1

Eine Möglichkeit, dies zu erreichen, ist die Verwendung eines SerializerMethodField. Das Folgende könnte etwas anders sein als Ihr Anwendungsfall, aber Sie können entsprechend anpassen. Es gibt andere Wege, dies auch zu erreichen, einschließlich des Überschreibens von Methoden, aber sie beruhen darauf, mit den inneren Funktionen von DRF mehr zu tun als hier relevant.

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') 

Ein Beispiel

>>> 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' 
    }, 
} 
+0

Kannst du das mit einer dynamischen Menge verschiedener Gruppen machen? –

2

Nehmen wir an, dass das kwdGroup Feld zu einem Modell der Beziehung Feld KeyWordGroup genannt .

Der Standard ListSerializer verwendet die to_representation Methode eine Liste der serialisierten Objekte darzustellen 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 
     ] 

Wir haben die ListSerializer zur Gruppe zum Beispiel die Ergebnisse ändern können:

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() 
       } 

Wir können dann Verwenden Sie die modifizierte VocabListSerializer mit der VocabSerializer.

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