我有一个带有活动的 Django 网站。在使用 django-toolbar 检查优化机会时,我发现活动订阅列表的视图非常低效。每个订阅它发出五个数据库请求,只是为了检查用户是否是成员。
我的模型结构如下:
class Subscription(models.Model):
user = models.ForeignKey(User, null=True)
activity = models.ForeignKey(Activity)
class MemberProfile(models.Model):
user = models.ForeignKey(User)
member_in = models.ManyToManyField(WorkYear, blank=True, null=True)
class WorkYear(models.Model):
year = models.SmallIntegerField(unique=True)
current = models.BooleanField(default=False, blank=True)
现在,要检查订阅的用户是否是会员,我们必须检查是否有MemberProfile
引用它,WorkYear
在其member_in
字段中current
设置为 true。
我有一个Subscription
被调用的属性,is_member
它返回了这个信息。在模板中,每次订阅都会调用此属性,从而导致大量数据库请求。而不是这样做,我想向视图中创建的 QuerySet 添加一个自定义字段。
我已经尝试过这个extra()
功能:
subscriptions = activity.subscription_set.extra(
select={
'is_member': 'SELECT current FROM activities_subscription LEFT OUTER JOIN (auth_user LEFT OUTER JOIN (members_memberprofile LEFT OUTER JOIN (members_memberprofile_member_in LEFT OUTER JOIN site_main_workyear ON members_memberprofile_member_in.workyear_id = site_main_workyear.id AND site_main_workyear.current = 1) ON members_memberprofile.id = members_memberprofile_member_in.memberprofile_id) ON auth_user.id = members_memberprofile.user_id) ON activities_subscription.user_id = auth_user.id'
},
tables=['site_main_workyear', 'members_memberprofile_member_in', 'members_memberprofile', 'auth_user']
).order_by('id')
这真的很复杂,由于某种原因它不起作用。重新加载页面后,Python 占用 100% CPU 并且没有响应。
有没有更好更简单的方法来做到这一点?如果没有,我做错了什么?