Django:如何根据第二个 table 的属性过滤内部连接?
Django: How to filter on inner join based on properties of second table?
我的问题很简单:在 Django 应用程序中,我有一个 table Users
和一个 table StatusUpdates
。在 StatusUpdates
table 中,我有一列 user
,它是指向 Users
的外键。我如何进行搜索,表达如下内容:
users.filter(latest_status_update.text__contains='Hello')
编辑:
请原谅我不够清晰。我想进行的查询类似于 "Give me all the users whose latest status update contains the text 'hello'"。在 Django 代码中,我会执行以下操作(这确实是低效且丑陋的):
hello_users = []
for user in User.objects.all():
latest_status_update = StatusUpdate.objects.filter(user=user).order_by('-creation_date')[0]
if latest_status_update.text.contains('Hello'):
hello_users.append(user)
return hello_users
编辑 2:
我已经找到了解决方案,但既然有人问我,这里是我模型的重要部分:
class User(models.Model):
...
class StatusUpdate(models.Model):
user = models.ForeignKey(User)
text = models.CharField(max_length=140)
creation_date = models.DateTimeField(auto_now_add=True, editable=False)
....
不确定我是否理解,你是不是想做类似
的事情
(StatusUpdates
.objects
.select_related("user")
.filter(text__contains = "hello")
.order_by("-updated")
.first())
这将 return 上次修改的 StatusUpdate(如果您有一个名为 updated 的字段存储上次修改的时间),它在文本字段中包含 "Hello"。如果 StatusUpdates 的 none 包含该字符串,它将 return None.
那么你可以这样做:
latest = (StatusUpdates
.objects
.select_related("user")
.filter(text__contains = "hello")
.order_by("-updated")
.first())
#then if you needed the user too
if latest is not None:
user = latest.user #which does not call the DB again since you selected related`
如果这不是您需要的,请提供更多详细信息(型号)并阐明您的需求
latest_status_updates = filter(lambda x: x.text.contains('hello'),
[
user.statusupdates_set.order_by('-creation_date').first()
for user in User.objects.all()
]
)
users = list(set([status_update.user for status_update in latest_status_updates]))
编辑:
现在我首先将每个用户的所有最新状态更新放入一个列表中,然后通过在 StatusUpdate class 中找到的文本字段进行过滤。在第二行中,我从过滤的状态更新中提取用户,然后生成一个唯一的用户列表。
希望对您有所帮助!
好的,我想我明白了:
from django.db.models import Max, F
User.objects\
.annotate(latest_status_update_id=Max('statusupdate__id'))\
.filter(
statusupdate__id=F('latest_status_update_id'),
statusupdate__text__icontains='hello'
)
有关详细信息,请参阅 this section of the Django documentation。
请注意: 我最终稍微改变了我的策略并采用了最高 ID 表示最新更新的策略。之所以如此,是因为我意识到用户可以同时 post 两次更新,这会破坏我的查询。
我的问题很简单:在 Django 应用程序中,我有一个 table Users
和一个 table StatusUpdates
。在 StatusUpdates
table 中,我有一列 user
,它是指向 Users
的外键。我如何进行搜索,表达如下内容:
users.filter(latest_status_update.text__contains='Hello')
编辑:
请原谅我不够清晰。我想进行的查询类似于 "Give me all the users whose latest status update contains the text 'hello'"。在 Django 代码中,我会执行以下操作(这确实是低效且丑陋的):
hello_users = []
for user in User.objects.all():
latest_status_update = StatusUpdate.objects.filter(user=user).order_by('-creation_date')[0]
if latest_status_update.text.contains('Hello'):
hello_users.append(user)
return hello_users
编辑 2:
我已经找到了解决方案,但既然有人问我,这里是我模型的重要部分:
class User(models.Model):
...
class StatusUpdate(models.Model):
user = models.ForeignKey(User)
text = models.CharField(max_length=140)
creation_date = models.DateTimeField(auto_now_add=True, editable=False)
....
不确定我是否理解,你是不是想做类似
的事情(StatusUpdates
.objects
.select_related("user")
.filter(text__contains = "hello")
.order_by("-updated")
.first())
这将 return 上次修改的 StatusUpdate(如果您有一个名为 updated 的字段存储上次修改的时间),它在文本字段中包含 "Hello"。如果 StatusUpdates 的 none 包含该字符串,它将 return None.
那么你可以这样做:
latest = (StatusUpdates
.objects
.select_related("user")
.filter(text__contains = "hello")
.order_by("-updated")
.first())
#then if you needed the user too
if latest is not None:
user = latest.user #which does not call the DB again since you selected related`
如果这不是您需要的,请提供更多详细信息(型号)并阐明您的需求
latest_status_updates = filter(lambda x: x.text.contains('hello'),
[
user.statusupdates_set.order_by('-creation_date').first()
for user in User.objects.all()
]
)
users = list(set([status_update.user for status_update in latest_status_updates]))
编辑: 现在我首先将每个用户的所有最新状态更新放入一个列表中,然后通过在 StatusUpdate class 中找到的文本字段进行过滤。在第二行中,我从过滤的状态更新中提取用户,然后生成一个唯一的用户列表。
希望对您有所帮助!
好的,我想我明白了:
from django.db.models import Max, F
User.objects\
.annotate(latest_status_update_id=Max('statusupdate__id'))\
.filter(
statusupdate__id=F('latest_status_update_id'),
statusupdate__text__icontains='hello'
)
有关详细信息,请参阅 this section of the Django documentation。
请注意: 我最终稍微改变了我的策略并采用了最高 ID 表示最新更新的策略。之所以如此,是因为我意识到用户可以同时 post 两次更新,这会破坏我的查询。