我知道使用 Django 无法按属性进行过滤,因为过滤是在数据库级别完成的,并且属性存在于 Python 代码中。但是,我有以下情况:
一方面,我有模型RegisteredUser
另一方面Subscription
。一个用户可以有多个订阅,一个订阅来自一个用户,一个用户有一个或没有有效订阅。
为了实现这一点,我有一个来自Subscription
to的外键RegisteredUser
和一个指向活动的属性subscription
(RegisteredUser
为该用户创建的最新订阅),如果他没有任何订阅,则没有。
过滤订阅“白金”、“黄金”、“白银”...的用户最有效的方法是什么?我可以做一个“获取所有订阅”,然后遍历它们以检查每个订阅是否匹配。但这真的很贵,如果我必须为每种订阅类型执行相同的过程,那么成本将是 s * u(其中s
是不同订阅u
的数量,是用户的数量)。
任何帮助将不胜感激。提前致谢!
更新:
当我第一次解释这个问题时,我没有包括所有与简化相关的模型。但是当您向我询问模型并且你们中的一些人还没有理解我(也许我不够清楚)时,这里有代码。我已经简化了模型并删除了现在不重要的代码。
我这里有什么?ARegisteredUser
可以有很多订阅(因为他可以根据需要多次更改),并且订阅仅来自一个用户。用户当前只有一个订阅,这是最新的订阅,由属性返回
subscription
。Subscription
附有Membership
,这是
slug
可以是:铂金,金,银等的模型。
我需要什么?我需要查找具有特定成员资格的人Content
。author
如果属性方法有效,我会这样做:
Content.objects.filter(author__id__in=RegisteredUser.objects.filter(
subscription__membership__slug="gold"))
但是我不能这样做,因为过滤时不能使用属性!
我认为我可以解决将属性创建的“虚拟”关系转换为真正的 ForeignKey 的问题,但这可能会导致副作用,因为我应该在每次用户更改其订阅时手动更新它,现在它是自动的!有更好的想法吗?
非常感谢!
class RegisteredUser(AbstractUser):
birthdate = models.DateField(_("Birthdate"), blank=True, null=True)
phone_number = models.CharField(_("Phone number"), max_length=9, blank=True, default="")
@property
def subscription(self):
try:
return self.subscriptions_set.filter(active=True).order_by("-date_joined",
"-created")[0]
except IndexError:
return None
class Subscription(models.Model):
date_joined = models.DateField(_("Date joined"), default=timezone.now)
date_canceled = models.DateField(_("Date canceled"), blank=True, null=True)
subscriber = models.ForeignKey(AUTH_USER_MODEL, verbose_name=_("Subscriber"),
related_name="subscriptions_set")
membership = models.ForeignKey(Membership, verbose_name=_("Membership"),
related_name="subscriptions_set")
created = models.DateTimeField(_("Created"), auto_now_add=True)
last_updated = models.DateTimeField(_("Last updated"), auto_now=True)
active = models.BooleanField(_("Active"), default=True)
class Membership(models.Model):
name = models.CharField(_("Name"), max_length=15)
slug = models.SlugField(_("Slug"), max_length=15, unique=True)
price = models.DecimalField(_("Price"), max_digits=6, decimal_places=2)
recurring = models.BooleanField(_("Recurring"))
duration = models.PositiveSmallIntegerField(_("Duration months"))
class Content(models.Model):
author = models.ForeignKey(AUTH_USER_MODEL, verbose_name=_("Author"),
related_name="contents_set")
title = models.CharField(_("Title"), max_length=50)
slug = models.SlugField(_("Slug"), max_length=70, unique=True)
content = RichTextField(_("Content"))
date = models.DateField(_("Date"), default=timezone.now)
published = models.BooleanField(_("Published"))