【问题标题】:django REST filter query by foreign key lookup_fielddjango REST过滤器查询外键lookup_field
【发布时间】:2019-03-04 05:00:16
【问题描述】:

我有一个时间 obj 序列化为 DRF。

型号:

class Time(TimeStampedModel):
    user = models.ForeignKey(
        'users.User', on_delete=models.CASCADE, related_name='time_logs')
    amount = models.DurationField()
    date_created = models.DateTimeField(auto_now_add=True)
    date_updated = models.DateTimeField(auto_now=True)

序列化器:

class TimeSerializer(serializers.ModelSerializer):
    user = serializers.HiddenField(default=serializers.CurrentUserDefault())

    class Meta:
        model = Time
        fields = ('__all__')
        extra_kwargs = {'date_created': {'read_only': True}, 'date_updated': {'read_only': True}}

视图集:

class UserTimeViewSet(viewsets.ModelViewSet):
    serializer_class = TimeSerializer
    queryset = Time.objects.all()

    def get_queryset(self):
        return Time.objects.filter(user=self.request.user)

网址

from rest_framework.routers import DefaultRouter

router = DefaultRouter()

router.register(r'users/time', UserTimeViewSet)

这给了我一个端点:/users/time/{id} 其中 {id} 是 Time obj id。当我尝试将端点修改为相同的 url 路由,而是通过覆盖序列化程序和 ViewSet 上的lookup_field 将用户 ID 作为 arg 传递给它(仅获取该用户的时间)时,我要么得到响应错误,要么得到 @ 987654328@

class UserTimeViewSet(viewsets.ModelViewSet):
    serializer_class = TimeSerializer
    queryset = Time.objects.all().select_related('user')
    lookup_field = 'user'

也试过了:

class UserTimeViewSet(generics.ListAPIView):
    serializer_class = TimeSerializer

    def get_queryset(self):
        user = self.kwargs['user']
        return Time.objects.filter(user=user)

如何通过用户 ID 获取与用户的关系的时间?

【问题讨论】:

  • 那么,您想输入 user_id 并检索 Time 对象....对吗?
  • @JPG 是的,我想输入 user_id 并取回 Time 对象,由具有该 id 的用户过滤
  • 那么,您需要返回时间实例无论登录用户如何
  • @JPG。是的。假设客户端有一个有效的密钥和权限来提出他们的请求,api.app.com/users/time/<user_id> 应该返回被请求用户的时间对象
  • 你所说的"请求用户的时间对象"是什么意思?在/users/time/ 端点,您将获得 已登录 用户 的时间对象

标签: django django-models django-rest-framework


【解决方案1】:

如果我的理解正确,这个视图类将发挥作用

class UserTimeViewSet(viewsets.ModelViewSet):
    serializer_class = TimeSerializer
    queryset = Time.objects.all()
    lookup_field = 'user' # add "lookup_field" attribute

    # remove "get_queryset()" method
    def get_queryset(self):
        return Time.objects.filter(user=self.request.user)

【讨论】:

  • 这仅在用户有一个时间对象时有效。如果用户有多次它会抛出 MultipleObjectsReturned get() 返回超过一次
  • 对不起...我忘记了这一点。我觉得最好将 filter 添加到您的列表 api 中,这样您的要求就会无缝地工作
  • 你能解释一下吗?你推荐一个单独的自定义过滤器?时间对象查询集需要通过lookup_field kwargs(在本例中为用户id)过滤
【解决方案2】:

如果用户只有一个 Time 对象,JPG 的另一个答案是有效的解决方案。但是,多个 objs 将返回 MultipleObjectsReturned get() returned more than one Time err

针对多个 obj 的解决方案是将视图集转换为 ListAPIView:

观看次数:

class UserTimeViewSet(generics.ListAPIView):
    serializer_class = TimeSerializer
    queryset = Time.objects.all()

    def get_queryset(self):
        return Time.objects.filter(user=self.kwargs['user'])

网址:

url(r'users/time/(?P<user>\d+)/$', UserTimeViewSet.as_view(), name='user_time'),

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-02-12
    • 2018-03-04
    • 2023-03-11
    • 2021-06-25
    • 2013-09-17
    • 2014-01-08
    • 2014-09-11
    • 1970-01-01
    相关资源
    最近更新 更多