django rest framework lookup_field 通过 OneToOneField

新手上路,请多包涵

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

期望的行为

用户查找通过用户名进行: /api/users/randall

扬声器查找也通过用户名进行: /api/speakers/randall

约束条件

并非所有用户都是演讲者。所有发言者都是用户。

模型.py

 from django.contrib.auth.models import User

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

序列化程序.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'

视图.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"

我已经尝试了 lookup_field 和序列化器类型的各种不同调用来使它无济于事。如果没有更多的代码,这可能是不可能的。我只是想知道我可以采取什么方向。

原文由 Randall Hunt 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 458
2 个回答

这就是我设法破解它的方式

模型.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

序列化程序.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'

查看.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'

原文由 Todor 发布,翻译遵循 CC BY-SA 4.0 许可协议

我从您的代码中唯一更改的是通过使用用户名而不是默认值进行过滤来覆盖 get_object 方法 pk 。 I also changed the lookup_field to a descriptive name and used ModelSerializer and StringRelated in the serializer.py .

模型.py

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

序列化器.py

 class SpeakerSerializer(serializers.ModelSerializer):
    user = serializers.StringRelatedField(read_only=True)

    class Meta:
        model = Speaker
        lookup_field = "username"
        fields = "__all__"

视图.py

 class SpeakerViewSet(ModelViewSet):
    queryset = Speaker.objects.all().select_related("user")
    serializer_class = SpeakerSerializer
    lookup_field = "username"

    def get_object(self):
        """Return the object for this view."""
        return get_object_or_404(self.queryset, user__username=self.kwargs["username"])

网址配置

 api/ ^speaker/$ [name='speaker-list']
 api/ ^speaker\.(?P<format>[a-z0-9]+)/?$ [name='speaker-list']
 api/ ^speaker/(?P<username>[^/.]+)/$ [name='speaker-detail']
 api/ ^speaker/(?P<username>[^/.]+)\.(?P<format>[a-z0-9]+)/?$ [name='speaker-detail']

原文由 PrynsTag 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题