按多对多字段 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
的语言 1
对 possibleMatches
中的用户进行升序排序。这是我到目前为止的代码和查询:
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关系,只保留指向sortingLanguage
的UserLanguage
,然后就可以对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>)
我需要一些涉及多对多关系的 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
的语言 1
对 possibleMatches
中的用户进行升序排序。这是我到目前为止的代码和查询:
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关系,只保留指向sortingLanguage
的UserLanguage
,然后就可以对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>)