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

如何在Django中按指定多对多关联的MovieTranslation排序?

解决方案:按指定语言的翻译标题排序Django Movie模型

要实现按lang='en'的MovieTranslation的title对Movie排序,核心是先精准关联到目标语言的翻译记录,再基于该记录的字段排序。以下是两种可行的实现方式,均在FilterSet类中完成:

方法一:使用FilteredRelation(Django 2.0+)

FilteredRelation可以创建一个过滤后的关联关系,仅包含符合条件的MovieTranslation实例,再通过该关联提取标题用于排序:

from django.db.models import FilteredRelation, Q
from django_filters import FilterSet, OrderingFilter

class MovieFilter(FilterSet):
    # 定义排序字段,前端可通过?ordering=title_en触发排序
    ordering = OrderingFilter(
        fields=(
            ('english_title', 'title_en'),
        )
    )

    class Meta:
        model = Movie
        fields = []

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # 标注当前Movie对应的英文翻译标题
        self.queryset = self.queryset.annotate(
            english_title=FilteredRelation(
                'movie_translations',
                condition=Q(movie_translations__lang='en')
            ).title
        )

方法二:使用Subquery + OuterRef(兼容更早Django版本)

通过子查询针对每个Movie单独获取其英文翻译的标题,避免多对多关联导致的排序混乱:

from django.db.models import Subquery, OuterRef
from django_filters import FilterSet, OrderingFilter

class MovieFilter(FilterSet):
    ordering = OrderingFilter(
        fields=(
            ('english_title', 'title_en'),
        )
    )

    class Meta:
        model = Movie
        fields = []

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # 子查询:获取当前Movie的第一条英文翻译标题
        en_title_subquery = MovieTranslation.objects.filter(
            movie=OuterRef('pk'),
            lang='en'
        ).values('title')[:1]
        self.queryset = self.queryset.annotate(
            english_title=Subquery(en_title_subquery)
        )

后续配置与注意事项

  1. 关联ViewSet:在你的MovieViewSet中指定该FilterSet:
from rest_framework import viewsets

class MovieViewSet(viewsets.ModelViewSet):
    queryset = Movie.objects.all()
    filter_class = MovieFilter
    # 其他如serializer_class等配置...
  1. 过滤无英文翻译的Movie:如果需要仅保留有英文翻译的条目,可在annotate前添加过滤:
self.queryset = self.queryset.filter(movie_translations__lang='en').annotate(...)
  1. 处理空值排序:若存在无英文翻译的Movie,english_title会为Null,不同数据库对Null值的排序逻辑不同(如PostgreSQL会将Null排在末尾),可根据需求调整。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 05:01:08