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/

也就是说,我会推荐一种更简单的方法。创建一个模型来保存您可能的用户类型,然后将其用作投票表中的外键:

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 回答