9

Ho alcuni problemi di serializzazione con django. Ho tre modelli, diciamo una scuola, una stanza e una scrivania (nome fittizio per esempio). Ogni scuola dispone di più stanze e ogni camera dispone di più desk.Django.rest_framework: come serializzare da uno a molti a molti?

Le classi e le loro relazioni simile a questa:

class School(models.Model): 
    name = models.CharField() 

class Room(models.Model): 
    name = models.CharField() 
    school_id = models.ForeignKey(School) 

class Desk(models.Model): 
    row = models.IntegerField() 
    col = models.IntegerField() 
    room_id = models.ForeignKey(Room) 

Voglio essere in grado di serializzare un elenco di scuola, ciascuna contenente direttamente tutti i banchi all'interno.

L'armadio ho ottenuto è stato scrivendo nel mio serialize.py tre serializzatore:

class DeskSerializer(serializers.ModelSerializer): 
    class Meta: 
     field = (row, col,) 

class RoomSerializer(serializers.ModelSerializer): 

    desks = DeskSerializer(source='desk_set', many=True) 
    class Meta: 
     field = (desks,) 

class SchoolSerializer(serializers.ModelSerializer): 

    rooms = RoomSerializer(source='room_set', many=True) 
    class Meta: 
     field = (name, rooms,) 

che restituiscono un elenco di scuole che contiene un elenco di stanza che contiene un elenco di scrivania, quando voglio una lista di scuola contenente un elenco di desk

Quale origine dovrei utilizzare nel serializzatore School per restituire direttamente la scrivania? Qualcosa come source = 'room_set.desk_set'? O forse usando una funzione transform_?

PS: il codice è scrivere da zero il post, si prega di ignorare gli eventuali errori di sintassi

risposta

16

Se ti sto comprensione correttamente, si desidera che il SchoolSerializer per restituire una struttura annidata 2 livelli di profondità, ma saltando il modello intermedio. Per fare questo, vorrei creare un metodo nel modello School per recuperare i Desk casi:

class School(models.Model): 
    ... 

    def get_desks(self): 
     rooms = Room.objects.filter(school=self) 
     desks = Desk.objects.filter(room__in=rooms) 
     return desks 

Poi, nel vostro SchoolSerializer includono un campo che utilizza tale metodo e rende le istanze restituite come si desidera tramite il vostro DeskSerializer:

la chiave per capire come funziona è che il metodo modello utilizzato come valore per l'argomento source deve semplicemente restituire le istanze di modello che di serializzatore. Il serializzatore lo prende da lì, rendendo gli oggetti comunque definiti dall'utente all'interno di quel serializzatore (in questo caso lo DeskSerializer).

Spero che questo aiuti.

+2

È possibile farlo in una query con: desks = Desk.objects.filter (room__school = self) –