【问题标题】:Django filtering on related models attributesDjango过滤相关模型属性
【发布时间】:2020-12-21 12:32:31
【问题描述】:
class Count(models.Model):
    start_time = models.DateTimeField(null = True, blank = True)
    end_time = models.DateTimeField(null = True, blank = True)

class AccessRecord(models.Model):
    user = models.ForeignKey(get_user_model(), related_name = 'accesses', on_delete = models.CASCADE)
    count = models.ForeignKey(Count, related_name = 'accesses', on_delete = models.CASCADE)

使用此模型方案,我如何根据用户过滤 Count 查询集?

例如,我希望每个计数对象都具有具有特定用户 ID 的第一个访问记录。

user_id = 2
all_counts = Count.objects.all()
list(filter(lambda x: x.accesses.first().user.pk == user_id, all_counts))

^^ 这会起作用。但是我得到一个列表而不是查询集(我仍然需要 order_by 等)

这里最好的选择是什么?

编辑。保证每个 Count 至少有一个访问记录。

【问题讨论】:

  • 你能解释一下为什么“first”访问记录吗?
  • 这与我的用例有关。我需要找到与该用户具有第一个访问记录的每个计数。

标签: python django


【解决方案1】:

您也可以在过滤器中使用accesses

因此Count.objects.filter(accesses__user_id=2)

但这将检索所有用于此用途的 Count,而不仅仅是每个第一个 AccessRecord 的那些。

因此,通过添加订单,您可以执行类似的操作

first_acccess_count = Count.objects.filter(accesses__user_id=2).order_by('start_time').first()

注意:first_acccess_count 可以是 None,如果用户还没有访问权限。

编辑:问题不清楚,查询应该这样做:我想要该 user_id 的每个计数对象。但是用户需要有第一个访问记录。

from django.db.models import Max
# First retrieve all first created AccessRecord's, by grouping on 
# Count and to find all lowest ids of AccessRecords. As lower id 
# can be seen as created first.
all_first_records_qs = AccessRecord.objects.values_list('count_id') \
    .annotate(max_id=Min('id')).values_list('max_id', flat=True)
# values_list returns a QuerySet, and thus lazy, which allows it to 
# be used as a subquery
all_counts = Count.objects.filter(
    accesses__user_id=2,
    accesses__id__in=all_first_records_qs,
)

【讨论】:

  • 对不起,我忘了说每个计数都保证至少有一个访问记录。另外,我认为您的解决方案不起作用。您正在搜索第一个 Count 对象。我想要该 user_id 的每个计数对象。但是用户需要有第一个访问记录。
  • 例如。具有两条访问记录(1st - user_id = 3, 2nd - user_id = 2)的 Count 对象仍会在您的逻辑中传递,而实际上该计数不是由用户 2“创建”的。
  • 但是你怎么知道伯爵是谁创造的呢? AccessRecord 上没有created_at 或其他内容,尽管您可以按 ID 订购访问权限。让我们看看我是否可以用更好的查询来更新答案。
  • 我编辑了我的答案,我想这次我做对了。
  • 如果我不清楚,我很抱歉。这正是我一直在寻找的。巧妙地使用注释。谢谢
猜你喜欢
  • 1970-01-01
  • 2017-06-22
  • 2019-08-23
  • 2020-01-19
  • 1970-01-01
  • 2021-09-25
  • 1970-01-01
  • 1970-01-01
  • 2021-09-04
相关资源
最近更新 更多