1

サイトの各タイプのユーザーの投票を追跡する投票システムを実装しようとしています。私の計画は、各ユーザー タイプの賛成票と合計票を追跡し、賛成票のパーセンテージを計算する投票モデルを作成することでした。

次のようにハードコードされています。

class Eduuser(AbstractUser):
    TYPE_1 = 'TY1'
    TYPE_2 = 'TY2'
    ...

   USER_TYPE_CHOICES = (
       (TYPE_1, 'Type 1'),
       (TYPE_2, 'Type 2'),
       ...
   )
   user_type = models.CharField(max_length=3, choices=USER_TYPE_CHOICES)


class Vote(models.Model):

    a = models.IntegerField(
        default=0, name=getattr(Eduuser, 'TYPE_1')+'_up')
    b = models.IntegerField(
        default=0, name=getattr(Eduuser, 'TYPE_2')+'_up')
    ...

    c = models.IntegerField(
        default=0, name=getattr(Eduuser, 'TYPE_1')+'_votes')
    d = models.IntegerField(
        default=0, name=getattr(Eduuser, 'TYPE_2')+'_votes')
    ...

    def perc(self):
        perc_array = []
        for user_type in getattr(Eduuser, 'USER_TYPE_CHOICES'):
            up = float(getattr(self, user_type[0]+'_up')) #Prevent int division
            votes = getattr(self, user_type[0]+'_votes')
            if votes==0:
                perc_array.append(0)
            else:
                perc_array.append(round(up/votes, 3))
        return perc_array

これ以上型を追加する予定はありませんが、コードをすっきりさせたいと思っています。ユーザータイプをループする私の最善の試みは次のとおりです。

class Eduuser(AbstractUser):
    ...

class Vote(models.Model):
    for user_type in getattr(Eduuser, 'USER_TYPE_CHOICES'):
        models.IntegerField(
            default=0, name=user_type[0]+'_up')
        models.IntegerField(
            default=0, name=user_type[0]+'_votes')

    def perc(self):
        ...

ただし、これはフィールドを保存しません(代入演算子がないためだと思います)。簡単な質問がいくつかあります。

1) 明示的に名前を割り当てずにフィールドを保存する方法はありますか? または、文字列名を変数に変換できますか (私が読んだ他の投稿から、これは悪い考えのようです)?

2) 私はこの投票のアイデアに論理的にアプローチしていますか? 私の一部は、複数のタイプのユーザーの投票を追跡するためのはるかに簡単なアプローチがあると感じています.

どんな助けでも大歓迎です!ありがとう!

4

2 に答える 2

1

django-model-utilsはChoicesヘルパーでこれをよりきれいにすることができます。

Vote次の方法でモデルを作成できます(テストされていません)。

from model_utils import Choices


class User(AbstractUser):
    USER_CHOICES = Choices(
        ('one', 'Type 1'),
        ('two', 'Type 2'),
    )

   user_type = models.CharField(max_length=10, choices=USER_CHOICES)


class Vote(models.Model):
    """
    A single vote on a `User`. Can be up or down.
    """
    VOTE_CHOICES = Choices(
        ('upvote'),
        ('downvote'),
    )

    user = models.ForeignKey(User)
    vote = models.CharField(max_length=10, choices=VOTE_CHOICES)

使用例– すべての「タイプ 1」ユーザーの賛成票数を取得します。

# retrieve all of the votes
all_votes = Vote.objects.all()
all_votes_count = len(all_votes)

# now retrieve all of the votes for users of ‘Type 1’    
type_one_votes = all_votes.filter(user__user_type=User.USER_CHOICES.one)
type_one_votes_count = len(type_one_votes)

# …and now filter the positive votes for ‘Type 1’ users
type_one_positives = type_one_votes.filter(vote=Vote.VOTE_CHOICES.upvote)
type_one_positive_vote_count = len(type_one_positives)

# etc.
于 2013-07-09T22:27:34.030 に答える
0

Django は、いくつかのメタクラスの動作を使用して、宣言に基づいてフィールドを作成するため、これは完全に簡単ではありません。モデル クラスにフィールドを動的に追加するために使用できる文書化されていない呼び出しがいくつかあります。この投稿を参照してください。

http://blog.jupo.org/2011/11/10/django-model-field-injection/

とは言っても、よりシンプルなアプローチをお勧めします。考えられるユーザー タイプを保持するモデルを作成し、それを vote テーブルの外部キーとして使用します。

class UserType(models.Model):
    type_name = models.CharField()

class Vote(models.Model):
    user_type = models.ForeignKey(UserType)
    total = models.PositiveIntegerField()

または、個々の投票を追跡し、必要に応じて合計して、投票を行ったユーザーまたは投票時のユーザーのタイプのみを記録します。投票後にユーザーがクラスを変更した場合に何をしたいかによっては、とにかくユーザーのタイプを保存する必要がある場合があります。

合計を追跡するだけなら、トランザクションの問題についてもっと慎重に考える必要があります。つまり、ユーザーを追跡し、一意性制約を適用することです。

于 2013-07-09T22:48:14.087 に答える