【问题标题】:How to query using a field from the first related object in Django?如何使用 Django 中第一个相关对象的字段进行查询?
【发布时间】:2021-10-14 01:38:45
【问题描述】:

我有以下型号:

class User(models.Model):
    username = models.CharField(max_length=255, unique=True)
    display_name = models.CharField(max_length=255)
    ...

class Profile(models.Model):
    user = models.ForeignKey(User)
    name = models.CharField(max_length=255)

在视图中,我有一个名为keyword 的参数。我想要做的是查询User 表中包含keyword 的任何用户username 字段OR display_name 字段,AND 也是第一个相关配置文件的name 字段。希望这是有道理的。有没有办法在一个查询中做到这一点?有些用户可能没有任何个人资料,因此也需要考虑在内。

到目前为止,我得到了这个:

from django.db.models import Q

def get_queryset(keyword):
    qs = User.objects.all()
    qs = qs.filter(Q(username__icontains=keyword), Q(display_name__icontains=keyword))
    return qs

感谢您的帮助!

【问题讨论】:

  • 您能否添加您自己的查询,然后我们继续?您还想包括没有个人资料的用户吗?
  • @ÇağatayBarın 刚刚添加
  • 用户可以拥有多个个人资料吗?您想在查询结果中包含没有个人资料的用户吗?你能详细说明first related profile's name field吗?对不起,我没有得到那部分
  • @ÇağatayBarın 是的,用户可以有多个配置文件,但只需要查询第一个(默认排序)。是的,我也想包括没有任何个人资料的用户。

标签: django django-models django-queryset


【解决方案1】:

我无法对此进行测试,它在第一次运行时可能无法正常工作,但可能是一个很好的起点。我也不确定性能,但是当你尝试这个时你能告诉我,我可以修复代码。不过,最好有一个最小的可重现示例。

from django.db.models import Q, OuterRef, Subquery

def get_queryset(keyword):
    first_profile = Profile.objects.filter(user_id=OuterRef('id'))
    qs = User.objects.filter(Q(username__icontains=keyword) | Q(display_name__icontains=keyword)).annotate(first_profile_name=Subquery(first_profile.values('name')[:1])).filter(Q(first_profile_name=None) | Q(first_profile_name__icontains=keyword))
    return qs

【讨论】:

  • 不,返回一个空查询集
  • 也许我弄错了。此查询将返回包含 username 或 displayname 中的关键字的用户实例。除此之外,如果没有配置文件实例,它将包括用户。如果有配置文件实例,它将检查第一个配置文件的名称,并且它还应该包含关键字。那正确吗?据我了解,必须匹配用户的用户名或显示名。你能确定这样的记录存在吗? (请注意使用 icontains 而不是 contains 来禁用区分大小写)
  • 您能否创建没有个人资料、只有一个个人资料、有多个个人资料(将关键字与第一个个人资料匹配,并将关键字与第二个个人资料匹配)的用户来测试各种场景。可能 first_profile 查询的顺序是错误的,因此您应该在该查询中包含 order_by。
  • 对配置文件的所有可能性表示同意,老实说,不确定order_by 是什么意思。你能再解释一下吗?
  • 如果没有结果,问题不在于顺序。我已经在我的数据库上尝试过这个查询并返回结果。您可以使用示例数据和表格创建一个简单的项目,以便我可以在本地对其进行测试吗?我在这里看不到问题,抱歉。
猜你喜欢
  • 1970-01-01
  • 2014-07-01
  • 2023-01-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-16
相关资源
最近更新 更多