按多对多字段 Django 中对象的值排序

Sorting by Value of Object in Many to Many Field Django

我需要一些涉及多对多关系的 Django 查询集的排序帮助。

我正在制作一个基于语言的对话应用程序,并且我刚刚完成了一个查询,该查询 returns 一个名为 possibleMatches 的查询集包含了可能想要与之聊天的用户。但是,现在我想根据他们在 user languages table 中使用的特定语言的 level 对这些用户进行排序。我相信解决方案在于使用 Django 的 annotate() 函数对查询集进行排序,但我一直无法找到执行此操作的确切语法。我也尝试过使用过滤关系,但是当 运行 它时,我收到一条错误消息,指出过滤关系不支持嵌套条件。

每个用户都有一个 id 和一个由多对多字段表示的 user languages 列表。每种用户语言对应一种user、一种language和一种level。为清楚起见,这是我的模型:

class CustomUser(AbstractUser):

    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)

class Language(models.Model):

    id = models.IntegerField(primary_key=True, choices=SUPPORTED_LANGUAGES)

class UserLanguage(models.Model):

    language = models.ForeignKey(Language, on_delete=models.DO_NOTHING)
    user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='languages', on_delete=models.DO_NOTHING)
    level = models.IntegerField(choices=LANGUAGE_PROFICIENCIES, null=False, blank=False)

无论如何,我想根据 level 的语言 1possibleMatches 中的用户进行升序排序。这是我到目前为止的代码和查询:

sortingLanguage= Language.objects.get(id=1)
possibleMatches.annotate(language_1="languages__language__id=sortingLanguage.id").order_by(language_1.level)

但我不断收到语法错误,而且我不确定 filter()、annotate()、When() 和 Case() 的正确组合是什么才能使其正常工作(我想我'将语法与过滤多对多关系的语法混淆)。有谁知道正确的语法是什么?非常感谢您。

可以先过滤many-to-many关系,只保留指向sortingLanguageUserLanguage,然后就可以对level进行排序该语言:

CustomUser.objects.filter(
    <b>languages__language=sortingLanguage</b>
).order_by(<b>'languages__level'</b>)

如果知道排序语言的id,就不用先把那个object读入内存,直接通过id过滤即可:

CustomUser.objects.filter(
    <b>languages__language_id=<i>1</i></b>
).order_by(<b>'languages__level'</b>)

您可以使用聚合来按 已过滤 级别中的最大级别排序:

如果知道排序语言的id,就不用先把那个object读入内存,直接通过id过滤即可:

from django.db.models import Max

CustomUser.objects.filter(
    languages__language_id=<i>1</i>
).annotate(
    highest_level=<b>Max('languages__level')</b>
).order_by(<b>'highest_level'</b>)