如何检测用户是否尝试再次投票?

时间:2015-05-27 05:10:23

标签: python flask peewee

我目前正在实施一个upvoting系统(在应用程序中不使用向下投票系统)。我设法在我的应用程序中为Post模型创建了一个upvote属性。该属性的默认值为0,如下所示:

models.py

class User(UserMixin, Model):
    username = CharField(unique= True)
    email = CharField(unique= True)
    password = CharField(max_length = 100)
    joined_at = DateTimeField(default = datetime.datetime.now)
    is_admin = BooleanField(default = False)
    confirmed = BooleanField(default = False)
    confirmed_on = DateTimeField(null=True)

    class Meta:
        database = DATABASE
        order_by = ('-joined_at',)

    def get_posts(self):
        return Post.select().where(Post.user == self)

    def get_stream(self):
        return Post.select().where(
            (Post.user == self)
        )

    @classmethod
    def create_user(cls, username, email, password, is_admin= False, confirmed = False, confirmed_on = None):
        try:
            with DATABASE.transaction():
                cls.create(
                username = username,
                email = email,
                password = generate_password_hash(password),
                is_admin = is_admin,
                confirmed = confirmed,
                confirmed_on = confirmed_on)
        except IntegrityError:
            raise ValueError("User already exists")

class Post(Model):
    timestamp = DateTimeField(default=datetime.datetime.now)
    user = ForeignKeyField(
        rel_model = User,
        related_name = 'posts'
    )
    name = TextField()
    content = TextField()
    upvotes = IntegerField(default=0)
    url = TextField()
    category = TextField()

    class Meta:
        database = DATABASE
        order_by = ('-timestamp',)

我设法通过让用户关注链接来增加价值:

stream.html

 <div class="voting_bar">
        <a href="/vote/{{post.id}}"><img src="/static/img/upvote.png"></a>
        <p>{{post.upvotes}}</p>
      </div>

这将激活具有相关路线的功能:

app.py

@app.route('/vote/<int:post_id>')
def upvote(post_id):
    posts = models.Post.select().where(models.Post.id == post_id)
    if posts.count() == 0:
        abort(404)
    post = models.Post.select().where(models.Post.id == post_id).get()
    query = models.Post.update(upvotes = (post.upvotes+1)).where(models.Post.id == post_id)
    query.execute()
    return redirect(url_for('index'))

我的问题是,如何检测用户是否已经投票?我不确定我该怎么做才能做到这一点。我的计划是,如果我确定用户是否试图再次投票,我会做的只是减少他们之前的投票。

5 个答案:

答案 0 :(得分:6)

我认为这里最好的方法是创建一个名为投票的单独表格,该表格将包含两列。一个将存储Post的id,另一个将存储User的id。表格中的每个条目或行都算作一票。如果用户尝试对特定帖子进行投票,则首先查询投票表,如果存在具有该用户ID的行。如果它不存在,则添加投票。如果它确实存在,那么您只需删除投票。要获取特定帖子的总投票数,您将再次查询投票表并计算具有给定帖子ID的行数。如果您希望将来添加downvote功能,这也可以使您的应用程序可扩展。

答案 1 :(得分:2)

根据Bidhan的回答,您可以实现以下内容:

class Upvote(Model):
    user = ForeignKeyField(User)
    post = ForeignKeyField(Post)

    class Meta:
        indexes = (
            (('user', 'post'), True),  # Unique index on user+post
        )

您可以添加发布方法:

def add_vote(self, user):
    try:
        with DATABASE.atomic():
             Vote.create(user=user, post=self)
    except IntegrityError:
        return False # User already voted
    else:
        return True # Vote added

def num_votes(self):
    return Vote.select().where(Vote.post == self).count()

同样只是提示,但您可以使用atomic代替transaction,因为前者支持嵌套。

答案 2 :(得分:1)

您需要在该帖子上维护一个(去掉的)用户列表。

答案 3 :(得分:0)

也许你可以在用户的​​个人资料中存储一个变量,该评论表明他们之前已经对评论进行了评价? 然后检查upvoter先前是否已经投票,并在保持计数的同时防止计数增加。

修改的 或者你可以创建一个列表来跟踪那些像这样投票的人:

class Post(Model):
    timestamp = DateTimeField(default=datetime.datetime.now)
    user = ForeignKeyField(
        rel_model = User,
        related_name = 'posts'
    )
    name = TextField()
    content = TextField()
    upvotes = IntegerField(default=0)
    upvoters = []
    url = TextField()
    category = TextField()

追加向post.upvoters投票的用户,然后在提高统计数据之前检查列表

答案 4 :(得分:0)

您为Django服务器中的每个用户创建一个帐户,并使用Django的内置授权模块对其进行身份验证。

https://docs.djangoproject.com/en/1.8/topics/auth/

[要检查其他版本,请将网址中的1.8更改为您想要的版本]

使用此功能,您可以确保只有1个用户使用Flag进行upvote。完成upvote时,将设置标志。