1

フィルタリングはデータベース レベルで行われ、プロパティは Python コードに存在するため、Django ではプロパティによるフィルタリングができないことを私は知っています。ただし、次のシナリオがあります。

片手には模型RegisteredUserを、もう片方には模型を持っていSubscriptionます。ユーザーは複数のサブスクリプションを持つことができます。サブスクリプションは 1 人のユーザーからのものであり、ユーザーはアクティブなサブスクリプションを 1 つ持っているか、まったく持っていません。

これを実装するために、からの外部キーSubscriptionRegisteredUser、そのプロパティsubscriptionRegisteredUserアクティブなもの (そのユーザーに対して最後に作成されたサブスクリプション) を指すか、サブスクリプションがない場合は何もありません。

サブスクリプションが「プラチナ」、「ゴールド」、「シルバー」のユーザーをフィルタリングする最も効率的な方法はどれですか? 「すべてのサブスクリプションをフェッチ」してから、それらを繰り返し処理して、それぞれが一致するかどうかを確認できます。しかし、それは非常に高価であり、サブスクリプションの種類ごとに同じプロセスを実行する必要がある場合、コストは s * u (sは異なるサブスクリプションuの数、 はユーザーの数) になります。

どんな助けでも大歓迎です。前もって感謝します!

アップデート:

最初に問題を説明したとき、少し単純化に関連するすべてのモデルを含めませんでした。しかし、あなたは私にモデルを求めていますが、あなたの何人かは私を理解していません (おそらく私は十分に明確ではありませんでした)。ここにコードがあります。モデルを単純化し、現在重要ではないコードを取り除きました。

私はここに何を持っていますか?ARegisteredUserは多くのサブスクリプションを持つことができ (彼は何度でも変更できるため)、サブスクリプションは 1 人のユーザーからのものです。ユーザーが現在持っているサブスクリプションは 1 つだけです。これは最新のサブスクリプションであり、プロパティによって返されます subscriptionSubscriptionが付属しており、プラチナ、ゴールド、シルバー等のバリエーションが可能なMembershipモデルです 。slug

私が必要なものは何?特定の種類のメンバーシップを持つユーザーを検索する必要がありますContentauthorプロパティ アプローチが機能する場合は、次のようにします。

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"))
4

2 に答える 2

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()
于 2013-08-05T22:40:04.483 に答える