2013-11-04 9 views
7

Ho due modelli: Utente e Biglietto. biglietteria ha una utente, utente ha molte BigliettiDjango Rest Framework, collegamento ipertestuale a una relazione nidificata

ho realizzato che quando vado a url /Users/1/biglietti, sto ottenendo l'elenco dei biglietti dell'utente.

voglio usare le relazioni ipertestuali, e qui è quello che vedo nella mia rappresentazione modello User:

"tickets": [ 
    "http://127.0.0.1:8000/tickets/5/", 
    "http://127.0.0.1:8000/tickets/6/" 
] 

Ma io voglio che sia come

"tickets": "http://127.0.0.1:8000/users/1/tickets" 

C'è un modo per farlo quello con DRF?

L'url:

url(r'^users/(?P<user_pk>\d+)/tickets/$', 
    views.TicketsByUserList.as_view(), 
    name='myuser-tickets'), 

La vista:

class TicketsByUserList(generics.ListAPIView): 
    model = Ticket 
    serializer_class = TicketSerializer 

    def get_queryset(self): 
     user_pk = self.kwargs.get('user_pk', None) 
     if user_pk is not None: 
      return Ticket.objects.filter(user=user_pk) 
     return [] 

serializzatore utente (ho provato a giocare con la definizione biglietti campo, cambiando il tipo, nome_vista, ma senza effetto):

class UserSerializer(serializers.HyperlinkedModelSerializer): 
    tickets = serializers.HyperlinkedRelatedField(many=True, view_name='ticket-detail') 

    class Meta: 
     model = MyUser 
     fields = ('id', 'nickname', 'email', 'tickets') 

Serializzatore biglietti:

class TicketSerializer(serializers.HyperlinkedModelSerializer): 
    user = serializers.HyperlinkedRelatedField(view_name='myuser-detail') 
    liked = serializers.Field(source='liked') 

    class Meta: 
     model = Ticket 
     fields = ('id', 'user', 'word', 'transcription', 'translation', 'liked', 'created', 'updated') 

risposta

15

È possibile utilizzare un SerializerMethodField per personalizzarlo. Qualcosa di simile a questo:

class UserSerializer(serializers.HyperlinkedModelSerializer): 
    tickets = serializers.SerializerMethodField('get_tickets') 

    def get_tickets(self, obj): 
     return "http://127.0.0.1:8000/users/%d/tickets" % obj.id 

    class Meta: 
     model = MyUser 
     fields = ('id', 'nickname', 'email', 'tickets') 

I hard-wired l'URL in là per brevità, ma si può fare una ricerca inversa altrettanto bene. Questo in pratica dice semplicemente di chiamare il metodo get_tickets invece del comportamento predefinito nella superclasse.

+0

Durante il tentativo di implementare la soluzione, ho capito che devo passare in qualche modo l'oggetto di richiesta al serializzatore, per passarlo alla funzione di inversione, per ottenere un URL assoluto. Ho risolto il problema passando un oggetto di richiesta dal metodo "invia" al campo nel mio serializzatore. Ma sento che ignorare un metodo di invio ogni volta che voglio avere oggetto richiesta nel mio serializzatore non è una buona idea. Qual è il modo migliore per ottenere la richiesta nel serializzatore? – optimistiks

+1

C'è un modo per [fornire un contesto aggiuntivo al serializzatore] (http://django-rest-framework.org/api-guide/serializers.html#including-extra-context). I documenti dimostrano la tua situazione esatta come il caso d'uso di esempio. –

+2

Nel metodo 'get_tickets' è possibile ottenere l'oggetto richiesta con' request = self.context.get ('request') ', quindi chiamare' reverse' come al solito. – Cartucho

0

Per la cronaca, ecco un esempio della soluzione completa in base alla risposta di Joe Holloway:

class WorkProjectSerializer(serializers.CustomSerializer): 
    issues = drf_serializers.SerializerMethodField() 

    def get_issues(self, obj): 
     request = self.context.get('request') 
     return request.build_absolute_uri(reverse('project-issue-list', kwargs={'project_id': obj.id})) 

    class Meta: 
     model = WorkProject 
     fields = '__all__' 
Problemi correlati