2

django-hitcountを使用して、データベースオブジェクトへのヒットを集計しています。オブジェクトごとのヒット数をカウントして、特定の時間範囲でヒット数が最も多いオブジェクトを特定したいと思います。アプリには、ここで関心のある2つのモデルがあります。

class Hit(models.Model):
    created         = models.DateTimeField(editable=False)
    ip              = models.CharField(max_length=40, editable=False)
    session         = models.CharField(max_length=40, editable=False)
    user_agent      = models.CharField(max_length=255, editable=False)
    user            = models.ForeignKey(User,null=True, editable=False)
    hitcount        = models.ForeignKey(HitCount, editable=False)

class HitCount(models.Model):
    hits            = models.PositiveIntegerField(default=0)
    modified        = models.DateTimeField(default=datetime.datetime.utcnow)
    content_type    = models.ForeignKey(ContentType,
                        verbose_name="content cype",
                        related_name="content_type_set_for_%(class)s",)
    object_pk       = models.TextField('object ID')
    content_object  = generic.GenericForeignKey('content_type', 'object_pk')

「ヒット」は各ヒットをタイムスタンプでログに記録し、HitCountはヒットの総数を保存します。オブジェクトごとに時間範囲内でヒットを取得するには、次のことを行う必要があります。

作成された日付でヒットをフィルタリングするcontent_objectごとのヒット数をカウントします(上記でフィルタリングされた時間範囲内)上記で計算されたカウントで並べ替えますcontent_objectとカウントを返します

これは非常に高額になる可能性があるため、1日1回の計算/キャッシュを計画しました。

最初のステップとして、時間範囲に関係なく、content_objectごとのヒット数をカウントしたいと思いました。

limited_hc = Hit.objects.all().values('hitcount__content_object').annotate(count = Count('hitcount__object_pk'))

私はすぐに問題に遭遇します:

キーワード'hitcount__content_object'をフィールドに解決できません。選択肢は、created、hitcount、id、ip、session、user、user_agentです。

少し掘り下げてみると、アノテーションと一般的な関係がうまく連携していないことがわかりました。content_objectの代わりにobject_pkを使用すると、正常に機能しますが、オブジェクトの名前がわかりません。

だから私の質問:同じ結果を達成するための代替手段は何ですか?オブジェクトごとにグループ化するだけでなく、名前を保持するにはどうすればよいですか?

私はモデル(content_type)とid(object_pk)を持っているので、これらをいつでも別々にプルできますが、それはエレガントではないようです。。。

4

1 に答える 1

1

Hitモデルに一般的な関係を追加する方が、おそらくより効率的です。

class Hit(models.Model):
    ...
    object_id = models.PositiveIntegerField()
    content_type = models.ForeignKey(ContentType)
    content_object = generic.GenericForeignKey('content_type', 'object_id')

次に、Hitに対してcount()クエリを直接実行します。

t = ContentType.objects.get_for_model(the_object_being_hit)
id = the_object_being_hit.id
count = Hit.objects.filter(
                   created__range=(from_timestamp, to_timestamp),
                   content_type = t,
                   object_id = id
                 ).count()

Django South移行システムを使用して、ヒットカウントのモデルを変更できます。また、メタクラスにモンキーパッチを適用した後でHitをサブクラス化することも、ニーズに合った独自のモデルを定義することもできます。

編集オブジェクトのクラス全体または複数のクラスのヒットをカウントする場合は、次のようにすることができます。

count = Hit.objects.filter(
                     created__range = myrange,
                     content_type__in = set_of_types
                   ).count()

ここで、set_of_typesは、呼び出しで作成されたリスト、またはテーブルget_for_modelの直接フィルタリングによって取得されたクエリセットのいずれかです。ContentType

count()メソッドの優れた点は、データベースでカウントを実行できることです。これにより、はるかに高速になります。

content_typeごとの内訳を取得するには、次のことを試してください。

counts = Hit.objects.filter(
                   created__range = myrange
                ).values(
                   'content_type'
                ).annotate(
                   Count('content_type')
                )

これにより、カウントとコンテンツタイプIDの辞書が返され、必要なものに非常に近くなります。

于 2010-11-19T04:53:30.197 に答える