2010-12-18 5 views
0

質問がある単純なアプリケーションを構築しています。各質問には2進投票(yes/no)があります。ユーザーあたりの投票を記録したいので、各ユーザーは質問ごとに1つの投票しか得られません(スタックのオーバーフローやredditに似ています)。モデルセーブメソッドから別のモデルのデータを操作する

質問にVote_noとVote_yes intフィールドがあります。これらは、投票が追加されるたびにトランザクションで更新される必要があります。 Voteモデルのsaveメソッドからこれを行うことはできますか?

class Question(models.Model): 
    part_isit = models.CharField(max_length=45) 
    part_if = models.CharField(max_length=90) 
    votes_no = models.IntegerField() 
    votes_yes = models.IntegerField() 
    author = models.ForeignKey(User) 
    create_date = models.DateField(auto_now_add=True) 

VOTE_CHOICES = (
    ('Y', 'Yes'), 
    ('N', 'No'), 
) 

class Vote(models.Model): 
    choice = models.CharField(max_length=1, choices=VOTE_CHOICES) 
    question = models.ForeignKey(Question) 
    author = models.ForeignKey(User) 
    create_date = models.DateField(auto_now_add=True) 
    def save(self): 
     # increment the questions vote totals 

     #save the vote 
     super(Vote, self).save(); 

答えて

1

次の質問に答えますか?

class Question(models.Model): 
    blablabla #your definition 

    def count_yes(self): 
     return Vote.objects.filter(question__exact = self, 
            choice__exact = 'Y').count() 
+0

ありがとうございます。私が本当に好きでないのは、スケーラビリティだけです。すべての投票オブジェクトをリストとして取得しています。 ORMに集約クエリを実行させたいと思います。 BTWにはタイプミスがあります(choiseは選択肢です)。 – Keyo

+0

私の間違いは、カウントのクエリがORMでどのように行われるかです。 – Keyo

1

私は少し異なるIgautierのメソッドを書き換えたい:

class Question(models.Model): 
    # your defn 

    def count_yes(self): 
     return self.votes_set.filter(choice='Y') 
    def count_no(self): 
     return self.votes_set.filter(choice='N') 

この(とIgautierの答え)の背後にある理由は、データがすべてのデータベースにすでに格納されていることである:総を持ちますこれらのメソッドが呼び出されるたびに追加のクエリが実行されるのを防ぎます。これは、保存時の余分な作業を意味し、データベースに格納されているデータが競合する可能性があります。

パフォーマンスが問題になることがわかっている場合は、キャッシュのクエリセット(johnny-cache、自動または別のキャッシングシステムを試してみる)を調べることができます。データベーストリガーさえも含みます。私はそれがあなたの要求ループからそれを動かすかもしれないと思います:データベースは書き込みが起こるたびに値を更新した後に見ます。明らかに、これはあなたのDBMSに少し依存します。

最後に、あなたの質問に対する直接的な回答ではありませんが、質問ごとに1人のユーザーにつき1つの票が記載されています。

class Vote(models.Model): 
    # Your defn 

    class Meta: 
     unique_together = (
      ('author', 'question'), 
     ) 

次に、その制約を真に保つためにアプリケーションロジックに頼る必要はありません。あなたはおそらくユーザーが自分の質問で投票するのを防ぐだろう。

+0

私は投票モデルの保存メソッドをオーバーライドして、質問テーブルに保存された投票値を増やすためのトランザクションを追加すると思っていました。 – Keyo

+0

Hmm。同時に2人の投票があった場合はどうなりますか?それぞれの追加はトランザクションになりますが、引き続き競合状態が存在します。 –

関連する問題