Django的高效替代品按属性过滤

时间:2013-07-23 00:38:08

标签: django django-models django-orm

我知道Django无法实现filtering by property,因为过滤是在数据库级别完成的,属性存在于Python代码中。但是,我有以下情况:

另一方面,我的模型RegisteredUser另一方面Subscription。用户可以有多个订阅,订阅来自一个用户,而用户有一个或没有活动订阅。

为了实现这一点,我有一个从SubscriptionRegisteredUser的外键和一个subscription的{​​{1}}指向活动的外键(最新创建的订阅)用户)或者如果他没有任何订阅则没有。

哪种方式可以过滤最有效的订阅“白金”,“黄金”,“白银”......的用户?我可以执行“获取所有订阅”,然后迭代它们以检查每个订阅是否匹配。但它真的很贵,如果我必须为每种订阅类型做同样的过程,那么成本就是s * u(其中RegisteredUser是不同订阅的数量,而s是用户数量。)

任何帮助将不胜感激。提前谢谢!

更新

当我第一次解释这个问题时,我没有包含所有与之相关的模型 简化小事。但是当你问我模型时,有些人还没有理解我 (也许我不够清楚)在这里你有代码。 我已经简化了模型并删除了现在不重要的代码。

我在这里有什么? u可以有多个订阅(因为他可能会更改它) 他想要多次,订阅只来自一个用户。用户只有 一个当前订阅,这是最新的订阅,由酒店返回 RegisteredUsersubscription附有Subscription,这是其模型 Membership可以是:铂金,黄金,白银等。

我需要什么?我需要查找slug具有特定类型成员资格的Content。 如果房产方法有效,我会这样做:

author

但我不能这样做,因为过滤时无法使用属性!

我认为我可以解决转换由此创建的“虚拟”关系的问题 将该属性转换为真正的ForeignKey,但这可能会导致副作用,因为我应该在每次用户更改其订阅时手动更新它,现在它是自动的!有更好的想法吗?

非常感谢!

Content.objects.filter(author__id__in=RegisteredUser.objects.filter(
    subscription__membership__slug="gold"))

2 个答案:

答案 0 :(得分:1)

最后,为了解决这个问题,我用一个真正的外键替换了subscription属性,并添加了一个信号,用RegisteredUser附加了创建的订阅。

外键:

subscription = models.ForeignKey(Subscription, verbose_name=_("Subscription"),
    related_name='subscriber_set', blank=True, null=True)

信号:

@receiver(post_save, sender=Subscription)
def signal_subscription_post_save(sender, instance, created, **kwargs):
    if created:
        instance.subscriber.subscription = instance
        instance.subscriber.save()

答案 1 :(得分:0)

我认为你的模特是这样的:

KIND = (("p", "platinum"), ("g","gold"), ("s","silver"),)

class RegisteredUser(models.Model):
    # Fields....

class Subscription(models.Model):
    kind = models.CharField(choices=KIND, max_len=2)
    user = models.ForeignKey(RegisteredUser, related_name="subscriptions")

现在,您可以这样做:

gold_users = RegisteredUser.objects.filter(subscriptions_kind="g")
silver_users = RegisteredUser.objects.filter(subscriptions_kind="s")
platinum_users = RegisteredUser.objects.filter(subscriptions_kind="p")

使其适应您的模型

希望帮助

修改

Now, With your models, I think you want something like:

content_of_golden_users = Content.objects.filter(author__subscriptions_set__membership__slug="golden")

content_of_silver_users = Content.objects.filter(author__subscriptions_set__membership__slug="silver")

content_of_platinum_users = Content.objects.filter(author__subscriptions_set__membership__slug="platinum")