DRF ViewSet双Lookup字段始终为None无法查询数据求助
解决方案
你遇到的user_lookup和profile_lookup为None,核心问题大概率是URL参数名与视图集内获取参数的名称不匹配,或是未正确重写DRF视图集的查询逻辑来支持多字段查找。以下是具体修复步骤和代码示例:
1. 确认模型关联逻辑
先确保模型的关联关系正确(如果已有可跳过):
from django.contrib.auth.models import AbstractUser from django.db import models class CustomUser(AbstractUser): pass class UserProfile(models.Model): # 一对一关联CustomUser,设置related_name方便反向查询 user = models.OneToOneField(CustomUser, on_delete=models.CASCADE, related_name='profile') # 自定义字段,如昵称、手机号等 class UserEmails(models.Model): # 关联CustomUser,支持一个用户多条邮箱记录 user = models.ForeignKey(CustomUser, on_delete=models.CASCADE, related_name='emails') email = models.EmailField(unique=True) # 自定义字段,如是否为主邮箱等
2. 序列化器实现
保持基础序列化逻辑即可:
from rest_framework import serializers from .models import UserEmails class UserEmailsSerializer(serializers.ModelSerializer): class Meta: model = UserEmails fields = '__all__'
3. 自定义视图集(核心修复)
重写get_queryset方法,手动从URL参数中获取user_id和profile_id,同时验证二者的关联合法性:
from rest_framework import viewsets from rest_framework.exceptions import NotFound from .models import UserEmails, CustomUser from .serializers import UserEmailsSerializer class UserEmailsViewSet(viewsets.ReadOnlyModelViewSet): serializer_class = UserEmailsSerializer queryset = UserEmails.objects.all() def get_queryset(self): # 从URL路由参数中取出user_id和profile_id user_id = self.kwargs.get('user_id') profile_id = self.kwargs.get('profile_id') # 验证用户存在,且profile_id属于该用户 try: user = CustomUser.objects.get(id=user_id) if user.profile.id != int(profile_id): raise NotFound("用户ID与资料ID不匹配") except CustomUser.DoesNotExist: raise NotFound("用户不存在") # 返回该用户的所有邮箱记录 return self.queryset.filter(user_id=user_id)
4. 配置正确的URL路由
确保URL中的参数名与视图集内self.kwargs获取的名称完全一致:
from django.urls import path from .views import UserEmailsViewSet urlpatterns = [ # 路由参数名必须是user_id和profile_id,与视图集内取值名称对应 path('user-emails/<int:user_id>/<int:profile_id>/', UserEmailsViewSet.as_view({'get': 'list'}), name='user-emails-list'), ]
常见错误排查
- 参数名不匹配:如果URL中写的是
user_pk而视图集里取user_id,必然会得到None,务必保证两者名称完全一致 - 未验证关联合法性:跳过用户与资料的关联验证,可能返回不属于目标资料的邮箱数据
- 未重写查询逻辑:DRF默认只支持单个
lookup_field(默认是pk),必须手动重写get_queryset或get_object来处理多字段查找
内容的提问来源于stack exchange,提问作者Mohammad Asadi
相关产品推荐
相关产品推荐

