django rest framework lookup_field 通过 OneToOneField
django rest framework lookup_field through OneToOneField
https://gist.github.com/ranman/3d97ea9054c984bca75e
期望的行为
用户查找通过用户名进行:/api/users/randall
说话人查找也通过用户名进行:/api/speakers/randall
约束条件
并非所有用户都是演讲者。所有演讲者都是用户。
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"
我尝试了 lookup_field 和序列化器类型的各种不同调用,但都没有成功。如果没有更多的代码,这可能是不可能的。我只是想知道我可以采取什么方向。
你试过这种方法吗?
class SpeakerViewSet(viewsets.ModelViewSet):
queryset = Speaker.objects.all().select_related('user')
serializer_class = SpeakerSerializer
filter_backends = (filters.DjangoFilterBackend,)
filter_fields = ('user', 'user__username',)
这就是我破解它的方法
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'
我正在使用用户 ID [GET / Update] 获取用户设置
urls.py
path('user/<int:user_id>/settings/preferences/', UserPreferenceSettingsView.as_view(), name="settings_preferences")
models.py
class UserSetting(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
adult_lock = models.BooleanField(default=False)
child_lock = models.BooleanField(default=False)
promotional_email = models.BooleanField(default=True)
update_email = models.BooleanField(default=True)
updated_at = models.DateTimeField(auto_now=True)
views.py
class UserPreferenceSettingsView(generics.RetrieveUpdateAPIView):
http_method_names = ['get', 'patch']
serializer_class = UserPreferenceSettingsSerializer
def get_object(self):
lookup_field = self.kwargs["user_id"]
return get_object_or_404(UserSetting, user__pk=lookup_field)
如果您需要从 username
获取,只需将 user_id to username
和 url <int:user_id>
替换为 <username> or <str:username>
我对您的代码所做的唯一更改是通过使用用户名而不是默认 pk
进行过滤来覆盖 get_object
方法。我还将 lookup_field
更改为描述性名称,并在 serializer.py
.
中使用了 ModelSerializer
和 StringRelated
models.py
class Speaker(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
serializer.py
class SpeakerSerializer(serializers.ModelSerializer):
user = serializers.StringRelatedField(read_only=True)
class Meta:
model = Speaker
lookup_field = "username"
fields = "__all__"
views.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"])
urlconf
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']
https://gist.github.com/ranman/3d97ea9054c984bca75e
期望的行为
用户查找通过用户名进行:/api/users/randall
说话人查找也通过用户名进行:/api/speakers/randall
约束条件
并非所有用户都是演讲者。所有演讲者都是用户。
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"
我尝试了 lookup_field 和序列化器类型的各种不同调用,但都没有成功。如果没有更多的代码,这可能是不可能的。我只是想知道我可以采取什么方向。
你试过这种方法吗?
class SpeakerViewSet(viewsets.ModelViewSet):
queryset = Speaker.objects.all().select_related('user')
serializer_class = SpeakerSerializer
filter_backends = (filters.DjangoFilterBackend,)
filter_fields = ('user', 'user__username',)
这就是我破解它的方法
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'
我正在使用用户 ID [GET / Update] 获取用户设置
urls.py
path('user/<int:user_id>/settings/preferences/', UserPreferenceSettingsView.as_view(), name="settings_preferences")
models.py
class UserSetting(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
adult_lock = models.BooleanField(default=False)
child_lock = models.BooleanField(default=False)
promotional_email = models.BooleanField(default=True)
update_email = models.BooleanField(default=True)
updated_at = models.DateTimeField(auto_now=True)
views.py
class UserPreferenceSettingsView(generics.RetrieveUpdateAPIView):
http_method_names = ['get', 'patch']
serializer_class = UserPreferenceSettingsSerializer
def get_object(self):
lookup_field = self.kwargs["user_id"]
return get_object_or_404(UserSetting, user__pk=lookup_field)
如果您需要从 username
获取,只需将 user_id to username
和 url <int:user_id>
替换为 <username> or <str:username>
我对您的代码所做的唯一更改是通过使用用户名而不是默认 pk
进行过滤来覆盖 get_object
方法。我还将 lookup_field
更改为描述性名称,并在 serializer.py
.
ModelSerializer
和 StringRelated
models.py
class Speaker(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
serializer.py
class SpeakerSerializer(serializers.ModelSerializer):
user = serializers.StringRelatedField(read_only=True)
class Meta:
model = Speaker
lookup_field = "username"
fields = "__all__"
views.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"])
urlconf
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']