【发布时间】:2017-04-12 08:49:55
【问题描述】:
我一直在尝试优化我在 Django 中的查询以减少我的 postgres 数据库命中,所以这里是这个问题的简化版,相关模型
型号:
class SentEmail(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
sent_date = models.DateTimeField(default=timezone.now)
sender = models.EmailField()
class AppUser(models.Model):
user= models.OneToOneField(User, primary_key=True)
is_active= models.BooleanField(default= False)
expiration_date = models.DateTimeField(default=make_default_expiration_date) #note : 90 days after the creation
User 是标准的 Django 身份验证用户,具有用户名、密码和其他内容。我想要做的是为活跃用户检索AppUser 的各种数据以及与他们有关的最后一个SentEmail。目前,我有这个。
查看:
active_users = Language_new.objects.filter(expiration_date__gt=timezone.now(),
is_active=True)
如果我想包含最后发送的电子邮件,我会这样做
active_users = Language_new.objects.filter(expiration_date__gt=timezone.now(),
is_active=True).prefetch_related(
Prefetch(
"sentemail",
queryset=SentEmail.objects.filter().latest('sent_date'),
to_attr="last_sentemail"
))
问题:
Django 是否足够聪明,可以在这里建立关系:queryset=SentEmail.objects.filter().latest('sent_date')?如果没有,我如何引用filter() 中的每个用户?
另外,由于每个AppUser 可能没有“最新”sentemail,我该如何处理这种查询中的DoesNotExist?
代码执行:
执行这段代码会给我一个 AttributeError
AttributeError: 'SentEmail' object has no attribute '_iterable_class'
指向这条线:to_attr="last_sentemail"。我不知道为什么。
丑陋的解决方案:
请注意,我有一个如下所示的可行解决方案:
active_users = Language_new.objects.filter(expiration_date__gt=timezone.now(),
is_active=True)
active_users = list(active_users)
for user in active_users:
last_sent_mail = SentEmail.objects.filter(user=active_user.user)
if last_sent_mail.exists():
setattr(user, 'last_sent_mail_date', last_sent_mail.latest('sent_date').sent_date)
else:
setattr(user, 'last_sent_mail_date', 'None')
它有效,但我认为我们都同意它不是最好的。
注意:这里我直接检索最后一个sentemail 的日期,但完整的sentemail 或其日期都对我有用。
谢谢。
【问题讨论】:
标签: python django postgresql django-queryset