Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

django rest framework lookup_field through OneToOneField

Tags:

https://gist.github.com/ranman/3d97ea9054c984bca75e

Desired Behavior
User lookup happens by the username: /api/users/randall
Speaker lookup happens by the username as well: /api/speakers/randall

Constraints
Not all users are speakers. All speakers are users.

models.py

from django.contrib.auth.models import User

class Speaker(models.Model):
    user = models.OneToOneField(User)

serializers.py

class UserSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = User
        fields = ('url', 'username', 'email', 'groups')
        lookup_field = 'username'
 
class SpeakerSerializer(serializers.HyperlinkedModelSerializer):
    user = serializers.HyperlinkedRelatedField(
        view_name='user-detail',
        read_only=True,
        lookup_field='username'
    )
    class Meta:
        model = Speaker
        lookup_field = 'user'

views.py

class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    lookup_field = 'username'
    
class SpeakerViewSet(viewsets.ModelViewSet):
    queryset = Speaker.objects.all().select_related('user')
    serializer_class = SpeakerSerializer
    lookup_field = "user"

I've tried various different invocations of lookup_field and serializer types to get this working to no avail. It may not be possible without a lot more code. I'm just wondering what direction I can take.

like image 703
Randall Hunt Avatar asked Mar 16 '15 00:03

Randall Hunt


1 Answers

This is how I managed to hack it

models.py

from django.db import models    
from django.contrib.auth.models import User

class Speaker(models.Model):
    user = models.OneToOneField(User)

    @property
    def user__username(self):
        return self.user.username
    
    def __unicode__(self):
        return self.user.username

serializers.py

from .models import Speaker
from rest_framework import serializers
from django.contrib.auth.models import User

class UserSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = User
        fields = ('url', 'username', 'email', 'groups')
        lookup_field = 'username'

class SpeakerSerializer(serializers.HyperlinkedModelSerializer):
    user = serializers.HyperlinkedRelatedField(
        view_name='user-detail',
        read_only=True,
        lookup_field='username'
    )
    class Meta:
        model = Speaker
        fields = ('url', 'user')
        lookup_field = 'user__username'

view.py

from .models import Speaker
from .serializers import SpeakerSerializer, UserSerializer

from rest_framework import viewsets
from django.contrib.auth.models import User

class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    lookup_field = 'username'

class SpeakerViewSet(viewsets.ModelViewSet):
    queryset = Speaker.objects.all().select_related('user')
    serializer_class = SpeakerSerializer
    lookup_field = 'user__username'
like image 63
Todor Avatar answered Oct 02 '22 12:10

Todor