Ich habe ein Modell, das so aussieht:
class Category(models.Model):
parentCategory = models.ForeignKey('self', blank=True, null=True, related_name='subcategories')
name = models.CharField(max_length=200)
description = models.CharField(max_length=500)
Ich habe es geschafft, mit dem Serializer eine flache JSON-Darstellung aller Kategorien zu erhalten:
class CategorySerializer(serializers.HyperlinkedModelSerializer):
parentCategory = serializers.PrimaryKeyRelatedField()
subcategories = serializers.ManyRelatedField()
class Meta:
model = Category
fields = ('parentCategory', 'name', 'description', 'subcategories')
Was ich jetzt tun möchte, ist, dass die Liste der Unterkategorien eine Inline-JSON-Darstellung der Unterkategorien anstelle ihrer IDs enthält. Wie würde ich das mit dem Django-Rest-Framework machen? Ich habe versucht, es in der Dokumentation zu finden, aber es scheint unvollständig.
quelle
KeyError at /api/category/ 'subcategories'
. Übrigens danke für deine superschnellen Antworten :)Die Lösung von @ wjin hat für mich hervorragend funktioniert, bis ich auf das Django REST Framework 3.0.0 aktualisiert habe, das to_native nicht mehr unterstützt . Hier ist meine DRF 3.0-Lösung, die eine geringfügige Modifikation darstellt.
Angenommen, Sie haben ein Modell mit einem selbstreferenziellen Feld, z. B. Kommentare mit Thread in einer Eigenschaft namens "Antworten". Sie haben eine Baumdarstellung dieses Kommentarthreads und möchten den Baum serialisieren
Definieren Sie zunächst Ihre wiederverwendbare RecursiveField-Klasse
Verwenden Sie dann für Ihren Serializer das RecursiveField, um den Wert von "Antworten" zu serialisieren.
Einfach peasy, und Sie benötigen nur 4 Codezeilen für eine wiederverwendbare Lösung.
HINWEIS: Wenn Ihre Datenstruktur komplizierter ist als ein Baum, z. B. ein gerichteter azyklischer Graph (FANCY!), Können Sie das Paket von @ wjin ausprobieren - sehen Sie sich seine Lösung an. Ich hatte jedoch keine Probleme mit dieser Lösung für MPTTModel-basierte Bäume.
quelle
print self.parent.parent.__class__
undprint self.parent.parent
Eine weitere Option, die mit Django REST Framework 3.3.2 funktioniert:
quelle
Spät zum Spiel hier, aber hier ist meine Lösung. Nehmen wir an, ich serialisiere ein Blah mit mehreren Kindern vom Typ Blah.
Mit diesem Feld kann ich meine rekursiv definierten Objekte mit vielen untergeordneten Objekten serialisieren
Ich habe ein rekursives Feld für DRF3.0 geschrieben und es für pip https://pypi.python.org/pypi/djangorestframework-recursive/ gepackt.
quelle
Blah
und ein Feld namens aufgerufen hat,child_blahs
das aus einer Liste vonBlah
Objekten besteht.queryset=Class.objects.filter(level=0)
. Es kümmert sich um den Rest der Dinge selbst.Dieses Ergebnis konnte ich mit a erzielen
serializers.SerializerMethodField
. Ich bin mir nicht sicher, ob dies der beste Weg ist, habe aber für mich gearbeitet:quelle
Eine andere Möglichkeit wäre, in der Ansicht zu rekursieren, die Ihr Modell serialisiert. Hier ist ein Beispiel:
quelle
Ich hatte kürzlich das gleiche Problem und fand eine Lösung, die bis jetzt zu funktionieren scheint, selbst für willkürliche Tiefen. Die Lösung ist eine kleine Modifikation der von Tom Christie:
Ich bin mir nicht sicher, ob es in jeder Situation zuverlässig funktionieren kann ...
quelle
Dies ist eine Anpassung der Caipirginka-Lösung, die auf drf 3.0.5 und django 2.7.4 funktioniert:
Beachten Sie, dass der CategorySerializer in der 6. Zeile mit dem Objekt und dem Attribut many = True aufgerufen wird.
quelle
if 'branches'
geändert werden sollte zuif 'subcategories'
Ich dachte, ich würde mitmachen!
Über wjin und Mark Chackerian habe ich eine allgemeinere Lösung erstellt, die für direkte baumartige Modelle und Baumstrukturen mit einem Durchgangsmodell funktioniert. Ich bin mir nicht sicher, ob dies zu seiner eigenen Antwort gehört, aber ich dachte, ich könnte es genauso gut irgendwo hinstellen. Ich habe eine Option max_depth eingefügt, die eine unendliche Rekursion verhindert. Auf der tiefsten Ebene werden Kinder als URLs dargestellt (dies ist die letzte else-Klausel, wenn Sie lieber keine URL möchten).
quelle
else
Klausel bestimmte Annahmen über die Ansicht enthält. Ich musste meine durch ersetzen,return value.pk
damit Primärschlüssel zurückgegeben wurden, anstatt zu versuchen, die Ansicht rückwärts nachzuschlagen.Mit Django REST Framework 3.3.1 benötigte ich den folgenden Code, um Unterkategorien zu Kategorien hinzuzufügen:
models.py
serializers.py
quelle
Diese Lösung ähnelt fast den anderen hier veröffentlichten Lösungen, weist jedoch einen geringfügigen Unterschied in Bezug auf das Problem der Wiederholung von Kindern auf der Stammebene auf (wenn Sie der Meinung sind, dass dies ein Problem ist). Zum Beispiel
und wenn Sie diese Ansicht haben
Dies führt zu folgendem Ergebnis:
Hier
parent category
hatchild category
die a- und die json-Darstellung genau das, was wir wollen, dass sie dargestellt wird.aber Sie können sehen, dass es eine Wiederholung der
child category
auf der Wurzelebene gibt.Da einige Leute in den Kommentaren der oben veröffentlichten Antworten fragen, wie wir diese untergeordnete Wiederholung auf der Stammebene stoppen können , filtern Sie einfach Ihr Abfrageset mit
parent=None
wie folgtes wird das Problem lösen.
HINWEIS: Diese Antwort steht möglicherweise nicht in direktem Zusammenhang mit der Frage, aber das Problem hängt irgendwie zusammen. Auch dieser Verwendungsansatz
RecursiveSerializer
ist teuer. Besser, wenn Sie andere Optionen verwenden, die leistungsanfällig sind.quelle