Django:如何根据第二个表的属性过滤内连接?

时间:2016-10-25 17:38:14

标签: django django-models django-queryset

我的问题很简单:在Django应用中,我有一个表Users和一个表StatusUpdates。在StatusUpdates表中,我有一个列user,它是指向Users的外键。如何进行表达式的搜索:

users.filter(latest_status_update.text__contains='Hello')

修改

请原谅我的不清楚。我想提出的查询类似于"向我提供最新状态更新包含文字' 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)
  ....

3 个答案:

答案 0 :(得分:2)

好的,我想我明白了:

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意味着最新更新的策略。这是因为我意识到用户可以同时发布两个更新,这会破坏我的查询。

答案 1 :(得分:0)

不确定我明白了,您是否正在尝试做类似

的事情
StatusUpdates.objects.select_related("user").filter(text__contains = "hello").order_by("-updated").first()

这将返回最后修改的StatusUpdate(如果您有一个名为updated的字段,用于存储上次修改的时间),该字段在文本字段中包含“Hello”。如果StatusUpdates都不包含该字符串,则它将返回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` 

如果这不是您所需要的,请提供更多详细信息(型号)并说明您的需求

答案 2 :(得分:0)

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类中的文本字段进行过滤。在第二行中,我从过滤后的状态更新中提取用户,然后生成唯一的用户列表。

我希望这有帮助!