Includere intermediario (attraverso il modello) nelle risposte in Django Resto Quadro

Ho una domanda su come affrontare m2m /attraverso modelli e la loro presentazione in django resto del quadro. Facciamo un esempio classico:

models.py:

from django.db import models

class Member(models.Model):
    name = models.CharField(max_length = 20)
    groups = models.ManyToManyField('Group', through = 'Membership')

class Group(models.Model):
    name = models.CharField(max_length = 20)

class Membership(models.Model):
    member = models.ForeignKey('Member')
    group = models.ForeignKey('Group')
    join_date = models.DateTimeField()

serializers.py:

imports...

class MemberSerializer(ModelSerializer):
    class Meta:
        model = Member

class GroupSerializer(ModelSerializer):
    class Meta:
        model = Group

views.py:

imports...

class MemberViewSet(ModelViewSet):
    queryset = Member.objects.all()
    serializer_class = MemberSerializer

class GroupViewSet(ModelViewSet):
    queryset = Group.objects.all()
    serializer_class = GroupSerializer

Quando GETing un’istanza di Socio, mi è successo di ricevere tutti i membri campi e anche i suoi gruppi – però ho solo i gruppi di dati, senza aggiunta di dettagli che deriva dall’Appartenenza a modello.

In altre parole, ho aspettare per ricevere:

{
   'id' : 2,
   'name' : 'some member',
   'groups' : [
      {
         'id' : 55,
         'name' : 'group 1'
         'join_date' : 34151564
      },
      {
         'id' : 56,
         'name' : 'group 2'
         'join_date' : 11200299
      }
   ]
}

Nota la join_date.

Ho provato tante soluzioni, tra cui, naturalmente, Django Resto-Quadro pagina ufficiale su di esso e nessuno sembra dare adeguata risposta chiara a questo proposito – che cosa devo fare per includere questi campi? L’ho trovato più straight-forward con django-tastypie ma erano altri problemi e preferiscono resto-quadro.

InformationsquelleAutor mllm | 2013-06-23



3 Replies
  1. 123

    Cosa ne dite…..

    Sul tuo MemberSerializer, definire un campo come:

    groups = MembershipSerializer(source='membership_set', many=True)

    e poi la tua iscrizione serializzatore è possibile creare questo:

    class MembershipSerializer(serializers.HyperlinkedModelSerializer):
    
        id = serializers.Field(source='group.id')
        name = serializers.Field(source='group.name')
    
        class Meta:
            model = Membership
    
            fields = ('id', 'name', 'join_date', )

    Che ha l’effetto complessivo di creazione di un serializzato valore, gruppi, che ha come sorgente l’appartenenza che si desidera, e quindi si utilizza un serializzatore personalizzato per tirare fuori il bit che si desidera visualizzare.

    EDIT: come ha commentato @bryanph, serializers.field è stato rinominato serializers.ReadOnlyField in DRF 3.0, quindi questo dovrebbe leggere:

    class MembershipSerializer(serializers.HyperlinkedModelSerializer):
    
        id = serializers.ReadOnlyField(source='group.id')
        name = serializers.ReadOnlyField(source='group.name')
    
        class Meta:
            model = Membership
    
            fields = ('id', 'name', 'join_date', )

    per qualsiasi moderne implementazioni

    • fyi, ho provato molte varianti di questo e io non posso ottenere questo lavoro. Questo non è nella documentazione ufficiale? Dove è membership_set definito?
    • membership_set è il default relative al nome del Membro -> Appartenenza
    • Il trucco per me a scoprire il “membership_set” nome. Ho avuto un modello, senza l’esplicita “related” nome”, quindi ho dovuto indovinare il nome di esso, attraverso la lettura dei documenti in Django molti a Molti.
    • questo funziona alla grande, grazie per il suggerimento. Penso tuttavia DRF in questo caso è un po ‘ un controsenso perché Membro della classe definisce già un m2m campo denominato gruppi e questa soluzione sembra ignorare il campo in serialiser, costringendola a punto la relazione inversa, attraverso il modello. Io non sono molto in DRF dettagli di implementazione, ma probabilmente con il modello di introspezione potrebbe essere consegnato automaticamente. solo un po ‘ di cibo per il pensiero 🙂
    • Ogni caso è possibile aggiornare noi se questo funziona con l’ultima versione di DRF? O almeno dire quale versione state usando? Non riesco a fare DRF per tornare attraverso il modello di campo – si finisce sempre con l’originale relazione (invece di Appartenenza, sarebbe sempre il rientro del Gruppo).
    • Sto usando DRF 3.5.3 e la soluzione di cui sopra ha funzionato. Tuttavia, io ora non riesco a capire come fare i serializzatori “aggiornabile”, ad esempio, creare un Gruppo con un gruppo di Membri tramite il Gruppo serializzatore. I dati non attraverso dal momento che stiamo usando ReadOnlyField().
    • Il mio punto di riferimento ogni volta che ho bisogno di scrivere il codice per molti per molti relazioni. Risparmiatore di vita.

  2. 13

    Ero di fronte a questo problema e la mia soluzione (usando DRF 3.6) è stato quello di utilizzare SerializerMethodField sull’oggetto e esplicitamente la query la tabella di Appartenenza, in questo modo:

    class MembershipSerializer(serializers.ModelSerializer):
        """Used as a nested serializer by MemberSerializer"""
        class Meta:
            model = Membership
            fields = ('id','group','join_date')
    
    class MemberSerializer(serializers.ModelSerializer):
        groups = serializers.SerializerMethodField()
    
        class Meta:
            model = Member
            fields = ('id','name','groups')
    
        def get_groups(self, obj):
            "obj is a Member instance. Returns list of dicts"""
            qset = Membership.objects.filter(member=obj)
            return [MembershipSerializer(m).data for m in qset]

    Questo restituirà un elenco di dicts per i gruppi chiave dove ogni dict è serializzato dal MembershipSerializer. A renderlo modificabile, è possibile definire una propria creazione/aggiornamento di metodo all’interno del MemberSerializer dove scorrere i dati di input e di creare in modo esplicito o aggiornamento di Appartenenza modello istanze.

  3. -1

    NOTA: Come un Ingegnere del Software, mi piace usare le Architetture e mi hanno profondamente lavorato su un Approccio a più livelli per lo Sviluppo in modo che sto andando essere una Risposta Rispetto ai Livelli.

    Come ho capito il Problema, Ecco la Soluzione
    models.py

    class Member(models.Model):
        member_id = models.AutoField(primary_key=True)
        member_name = models.CharField(max_length = 
    
    class Group(models.Model):
        group_id = models.AutoField(primary_key=True)
        group_name = models.CharField(max_length = 20)
        fk_member_id = models.ForeignKey('Member', models.DO_NOTHING, 
                                 db_column='fk_member_id', blank=True, null=True)
    
    class Membership(models.Model):
        membershipid = models.AutoField(primary_key=True)
        fk_group_id = models.ForeignKey('Group', models.DO_NOTHING, 
                                 db_column='fk_member_id', blank=True, null=True)
        join_date = models.DateTimeField()

    serializers.py

    import serializer
    
    class AllSerializer(serializer.Serializer):
        group_id = serializer.IntegerField()
        group_name = serializer.CharField(max_length = 20)
        join_date = serializer.DateTimeField()

    CustomModels.py

    imports...
    
        class AllDataModel():
            group_id = ""
            group_name = ""
            join_date = ""

    BusinessLogic.py

    imports ....
    class getdata(memberid):
        alldataDict = {}
        dto = []
        Member = models.Members.objects.get(member_id=memberid) #or use filter for Name
        alldataDict["MemberId"] = Member.member_id
        alldataDict["MemberName"] = Member.member_name
        Groups = models.Group.objects.filter(fk_member_id=Member)
        for item in Groups:
            Custommodel = CustomModels.AllDataModel()
            Custommodel.group_id = item.group_id
            Custommodel.group_name = item.group_name
            Membership = models.Membership.objects.get(fk_group_id=item.group_id)
            Custommodel.join_date = Membership.join_date
            dto.append(Custommodel)
        serializer = AllSerializer(dto,many=True)
        alldataDict.update(serializer.data)
        return alldataDict

    Si sarebbe tecnicamente, devono trasmettere la Richiesta di DataAccessLayer che dovrebbe restituire gli Oggetti Filtrati dal Livello di Accesso ai Dati, ma come devo Rispondere alla Domanda in Maniera Veloce quindi ho regolato il Codice a Livello di Logica di Business!

    • Si tratta di un Approccio Personalizzato, che io uso per la maggior parte delle mie API Rest sviluppi, come io non sono davvero un fan di lavorare con i Limiti, anche se Django Resto del Quadro è abbastanza flessibile!
    • Questo è il troppo sopra, progettato, inoltre, non utilizzare DRF.

Lascia un commento