ユーザーが自分のサイトに投稿した回数を数えて、サイトでランク付けできるようにしたいと考えています。まさにそれを行う美しいコードを書くことができましたが、それはユーザーごとに行われました。
ユーザーはフィールドごとに異なる量のポイントを取得するため、モデルの特定のフィールドと、ユーザーがそれらに値を入力したかどうかをチェックします。次に、これらの値に重みを掛けて合計スコアを求めます。
少しのコードよりも優れているものはありません。
class UserContribCounter(object):
"""Can count the number of points a user got for his contributions"""
weight_dict = {'poster':2, 'title':1}
def __init__(self, user):
if isinstance(user, User):
self.user = user
else:
raise Exception('Not a valid user instance.')
def set_contrib_points(self):
"""Some dark magic counts the number of times a certain field was filled out"""
self.unweighted = Movie.objects.filter(user = self.user).aggregate(poster=Count('poster'),title=Count('title'))
def get_contrib_points(self):
"""Multiplies the number of times a field was filled out with their weights to calculate the total number of points"""
try:
self.unweighted
except AttributeError:
self.set_contrib_points()
return sum([self.weight_dict[key] * value for key, value in self.unweighted.items()])
トップ 10 も表示したいので、トップ 10 のユーザーを取得する必要があります。これは、現時点では失敗し続けている複雑な集計を作成する必要があるか、次の方法でシグナルを使用できることを意味します。
モデルが保存されたら、post_save シグナルをキャッチします。次に、既存のクラスを使用してユーザーのポイントを再計算し、ユーザー プロファイルに保存します。このようにして、プロファイルの値でユーザーを並べ替えることができますが、これは簡単なことです。
問題は、モデルが保存されるたびに再カウントを行うこと、またはかなり複雑な集計関数を行うことのどちらがより効率的かということです。これは多くのことに依存することはわかっていますが、概念的な観点からは、どちらかを選択する理由があるはずです。集約でチェックするフィールドの一部はリレーショナルでもあることに注意してください。そのため、パフォーマンスにどのように影響するかはわかりません.
前もって感謝します、
tBuLi