Python 过滤Django中的最新条目和预取
我一直试图在Django中优化我的查询,以减少我的postgres数据库命中率,因此下面是针对这个问题简化的相关模型 型号: 而Python 过滤Django中的最新条目和预取,python,django,postgresql,django-queryset,Python,Django,Postgresql,Django Queryset,我一直试图在Django中优化我的查询,以减少我的postgres数据库命中率,因此下面是针对这个问题简化的相关模型 型号: 而User是标准的Django auth用户,具有用户名、密码和其他内容。我想做的是为活动用户检索AppUser的各种数据以及与他们相关的最后一封sentmail。现在,我有这个 视图: 如果我想包括上次发送的电子邮件,我会这样做 active_users = Language_new.objects.filter(expiration_date__gt=timezone
User
是标准的Django auth用户,具有用户名、密码和其他内容。我想做的是为活动用户检索AppUser
的各种数据以及与他们相关的最后一封sentmail
。现在,我有这个
视图:
如果我想包括上次发送的电子邮件,我会这样做
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=sentmail.objects.filter().latest('sent_date')
?如果不是,如何引用过滤器()中的每个用户
另外,由于可能没有针对每个AppUser
的“最新”sentmail
,我如何处理此类查询中的问题
代码执行:
执行此代码会给我一个AttributeError
AttributeError: 'SentEmail' object has no attribute '_iterable_class'
指向此行:至\u attr=“last\u sentmail”
。我不知道为什么
丑陋的解决方案:
请注意,我有一个如下所示的工作解决方案:
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')
这是可行的,但我想我们都同意这不是最好的
注意:在这里,我直接检索最后一封发送电子邮件的日期
,但完整的发送电子邮件
或其日期对我都有效
谢谢。试试:
class SentEmail(models.Model):
user = models.ForeignKey(
User, on_delete=models.CASCADE, related_name='sent_mails'
)
sent_date = models.DateTimeField(default=timezone.now)
sender = models.EmailField()
及
要检索上次发送的电子邮件,请执行以下操作:
last_mail = user.last_sent_mail
if last_mail:
print last_mail.sent_date
谢谢,它起作用了。我仍然没有直接处理模型来帮助我构建请求的习惯。只是一个输入错误,它应该是sent\u mails=self.user.sent\u mails.order\u by('sent\u date')
而不是sent\u mails=self.sent\u mails.order\u by('sent\u date')
很高兴能帮上忙。我已经按照你的建议更改了代码。
class SentEmail(models.Model):
user = models.ForeignKey(
User, on_delete=models.CASCADE, related_name='sent_mails'
)
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
@property
def last_sent_mail(self): # or last_sent_mail_date
sent_mails = self.user.sent_mails.order_by('sent_date')
return sent_mails[0] if sent_mails.exists() else None
last_mail = user.last_sent_mail
if last_mail:
print last_mail.sent_date