Disons que nous avons le modèle suivant:
class Classroom(models.Model):
room_number = [....]
class Teacher(models.Model):
name = [...]
tenure = [...]
classroom = models.ForeignKey(Classroom)
Disons qu'au lieu d'obtenir un résultat comme celui-ci selon la fonction ManyRelatedPrimaryKeyField:
{
"room_number": "42",
"teachers": [
27,
24,
7
]
},
faites-le retourner quelque chose qui inclut la représentation complète du modèle associé, comme:
{
"room_number": "42",
"teachers": [
{
'id':'27,
'name':'John',
'tenure':True
},
{
'id':'24,
'name':'Sally',
'tenure':False
},
]
},
Est-ce possible? Si c'est le cas, comment? Et est-ce une mauvaise idée?
Le moyen le plus simple consiste à utiliser l'argument de profondeur
class ClassroomSerializer(serializers.ModelSerializer):
class Meta:
model = Classroom
depth = 1
Cependant, cela n'inclura que les relations pour les relations en aval, ce qui dans ce cas n'est pas tout à fait ce dont vous avez besoin, car le champ des enseignants est une relation inverse.
Si vous avez des exigences plus complexes (par exemple, inclure des relations inverses, imbriquer certains champs, mais pas d'autres, ou imbriquer seulement un sous-ensemble spécifique de champs), vous pouvez imbriquer des sérialiseurs , par exemple ...
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
Notez que nous utilisons l'argument source sur le champ du sérialiseur pour spécifier l'attribut à utiliser comme source du champ. Nous pourrions supprimer l'argument source
en nous assurant plutôt que l'attribut teachers
existe en utilisant l'option nom_relié sur votre modèle Teacher
, c'est-à-dire. classroom = models.ForeignKey(Classroom, related_name='teachers')
Il convient de garder à l'esprit que les sérialiseurs imbriqués ne prennent actuellement pas en charge les opérations d'écriture. Pour les représentations en écriture, vous devez utiliser des représentations à plat régulières, telles que pk ou hyperlien.
Merci @ TomChristie !!! Tu m'as beaucoup aidé! Je voudrais mettre à jour un peu cela (à cause d'une erreur que j'ai commise)
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",)
Ceci peut aussi être accompli en utilisant un dandy très pratique Django emballé appelé drf-flex-fields . Nous l'utilisons et c'est vraiment génial. Vous venez de l'installer pip install drf-flex-fields
, passez-le dans votre sérialiseur, ajoutez expandable_fields
et bingo (exemple ci-dessous). Il vous permet également de spécifier des relations imbriquées profondes à l'aide de la notation par points.
from rest_flex_fields import FlexFieldsModelSerializer
class ClassroomSerializer(FlexFieldsModelSerializer):
class Meta:
model = Model
fields = ("teacher_set",)
expandable_fields = {"teacher_set": (TeacherSerializer, {"source": "teacher_set"})}
Ensuite, vous ajoutez ?expand=teacher_set
à votre URL et renvoie une réponse développée. J'espère que cela aidera quelqu'un, un jour. À votre santé!