web-dev-qa-db-ger.com

Wie beziehe ich verwandte Modellfelder mit Django Rest Framework ein?

Nehmen wir an, wir haben folgendes Modell:

class Classroom(models.Model):
    room_number = [....]

class Teacher(models.Model):
    name = [...]
    tenure = [...]
    classroom = models.ForeignKey(Classroom)

Angenommen, statt ein Ergebnis wie das folgende mit der ManyRelatedPrimaryKeyField-Funktion zu erhalten:

{
    "room_number": "42", 
    "teachers": [
        27, 
        24, 
        7
    ]
},

lassen Sie es etwas zurückgeben, das die vollständige zugehörige Modelldarstellung enthält, wie:

{
    "room_number": "42", 
    "teachers": [
        {
           'id':'27,
           'name':'John',
           'tenure':True
        }, 
        {
           'id':'24,
           'name':'Sally',
           'tenure':False
        }, 
    ]
},

Ist das möglich? Wenn das so ist, wie? Und ist das eine schlechte Idee?

132
Chaz

Am einfachsten ist es, das Tiefenargument zu verwenden

class ClassroomSerializer(serializers.ModelSerializer):
    class Meta:
        model = Classroom
        depth = 1

Dies schließt jedoch nur Beziehungen für Vorwärtsbeziehungen ein, was in diesem Fall nicht ganz der Fall ist, da das Lehrerfeld eine umgekehrte Beziehung ist.

Wenn Sie komplexere Anforderungen haben (z. B. umgekehrte Beziehungen einschließen, einige Felder verschachteln, andere jedoch nicht, oder nur eine bestimmte Teilmenge von Feldern verschachteln), können Sie Serialisierer verschachteln , z. B. ...

class TeacherSerializer(serializers.ModelSerializer):
    class Meta:
        model = Teacher
        fields = ('id', 'name', 'tenure')

class ClassroomSerializer(serializers.ModelSerializer):
    teachers = TeacherSerializer(source='teacher_set')

    class Meta:
        model = Classroom

Beachten Sie, dass wir das Argument source im Feld serializer verwenden, um das Attribut anzugeben, das als Quelle des Felds verwendet werden soll. Wir könnten das Argument source löschen, indem wir stattdessen sicherstellen, dass das Attribut teachers vorhanden ist, indem wir die Option related_name für Ihr Modell Teacher verwenden, d. H. classroom = models.ForeignKey(Classroom, related_name='teachers')

Beachten Sie, dass verschachtelte Serialisierer derzeit keine Schreibvorgänge unterstützen. Für beschreibbare Darstellungen sollten Sie normale flache Darstellungen verwenden, z. B. pk oder Hyperlinks.

211
Tom Christie

Vielen Dank @TomChristie !!! Sie haben mir sehr geholfen! Ich möchte das ein wenig aktualisieren (wegen eines Fehlers, auf den ich gestoßen bin)

class TeacherSerializer(serializers.ModelSerializer):
    class Meta:
        model = Teacher
        fields = ('id', 'name', 'tenure')

class ClassroomSerializer(serializers.ModelSerializer):
    teachers = TeacherSerializer(source='teacher_set', many=True)

    class Meta:
        model = Classroom
        field = ("teachers",)
30
Eliyahu Tauber

Dies kann auch mit einem handlichen Dandy Django erreicht werden, der als drf-flex-fields bezeichnet wird. Wir benutzen es und es ist ziemlich genial. Sie installieren es einfach pip install drf-flex-fields, Lassen es durch Ihren Serializer laufen, fügen expandable_fields Und Bingo hinzu (Beispiel unten). Außerdem können Sie tief verschachtelte Beziehungen mithilfe der Punktnotation angeben.

from rest_flex_fields import FlexFieldsModelSerializer

class ClassroomSerializer(FlexFieldsModelSerializer):
    class Meta:
        model = Model
        fields = ("teacher_set",)
    expandable_fields = {"teacher_set": (TeacherSerializer, {"source": "teacher_set"})}

Dann fügen Sie Ihrer URL ?expand=teacher_set Hinzu und es wird eine erweiterte Antwort zurückgegeben. Hoffe, das hilft irgendwann jemandem. Prost!

0
Paul Tuckett