You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Django REST Framework中带过滤条件查询外键值

Hey there! I see you're trying to filter the related Score objects when using StringRelatedField in Django REST Framework, and there's also a small syntax issue in your queryset code. Let's break this down and fix it step by step.

First, let's address the immediate syntax error in your view:

Your current User.objects.filter(score>=10) is invalid. To filter users who have at least one score >=10, you need to use Django's double-underscore notation for related fields: User.objects.filter(score__score__gte=10). But this only filters which users are returned, not which scores are included for each user.

To actually filter the scores that get serialized for each user (i.e., only return scores >=10 for a given user), StringRelatedField doesn't support filtering out of the box. Here are two solid solutions:

Solution 1: Use SerializerMethodField (Simple & Direct)

Replace StringRelatedField with SerializerMethodField so you can explicitly filter the related scores in the serializer itself. This gives you full control over which scores are included.

Update your serializer.py:

from rest_framework import serializers
from .models import User, Score

class UserDetailsSerializer(serializers.ModelSerializer):
    score = serializers.SerializerMethodField()

    class Meta:
        model = User
        fields = ('id', 'score', )

    def get_score(self, obj):
        # Filter scores where value is >=10, then return their string representation
        filtered_scores = obj.score.filter(score__gte=10)
        return [str(score) for score in filtered_scores]

Solution 2: Use Prefetch (Performance-Optimized)

If you're dealing with large datasets, using Prefetch will optimize your queries by avoiding the "N+1" problem. We'll prefetch only the filtered scores upfront, then let StringRelatedField use that prefiltered data.

Update your views.py:

from django.db.models import Prefetch
from rest_framework import viewsets
from .models import User, Score
from .serializer import UserDetailsSerializer

class UserDetailsRetrieveViewSet(viewsets.ModelViewSet):
    serializer_class = UserDetailsSerializer

    def get_queryset(self):
        # Prefetch only scores >=10 for each user
        filtered_scores = Prefetch(
            'score',
            queryset=Score.objects.filter(score__gte=10),
            to_attr='filtered_scores'
        )
        # Optional: Add a filter to only return users who have at least one valid score
        return User.objects.prefetch_related(filtered_scores)

Then update your serializer.py to use the prefiltered attribute:

class UserDetailsSerializer(serializers.ModelSerializer):
    score = serializers.StringRelatedField(many=True, source='filtered_scores')

    class Meta:
        model = User
        fields = ('id', 'score', )

Key Notes:

  • StringRelatedField uses the __str__ method of your Score model under the hood. Make sure your Score model has a __str__ defined (e.g., def __str__(self): return str(self.score)), otherwise you'll get the default object representation.
  • The Prefetch approach is better for performance because it reduces the number of database queries from N+1 to just 2 (one for users, one for filtered scores).

内容的提问来源于stack exchange,提问作者Sakthi Panneerselvam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:21:47