You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django:实现用户对单产品仅一次投票的功能咨询

没问题,我来一步步帮你实现这个单产品限投一次的功能,结合你给出的Product模型,咱们分几步来:

1. 先完善 Vote 模型的定义

首先在你的models.py里添加Vote类,核心是给product和user字段设置联合唯一约束——这相当于在数据库层面加了一道锁,从根源上阻止重复投票,同时也能让我们快速检查用户是否已投过票:

from django.db import models
from django.contrib.auth.models import User  # 假设你用Django自带的用户认证模型

class Product(models.Model):
    title = models.CharField(max_length=255)
    url = models.TextField()
    pub_date = models.DateTimeField()
    votes_total = models.IntegerField(default=1)
    image = models.ImageField(upload_to='product_images/', blank=True, null=True)  # 补全ImageField的必要参数

class Vote(models.Model):
    product = models.ForeignKey(Product, on_delete=models.CASCADE, related_name='votes')
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    voted_at = models.DateTimeField(auto_now_add=True)  # 记录投票时间,可选但推荐

    class Meta:
        # 关键约束:同一个用户对同一个产品只能有一条投票记录
        unique_together = ('product', 'user')
        # Django 2.2+ 也可以用更灵活的 UniqueConstraint:
        # constraints = [
        #     models.UniqueConstraint(fields=['product', 'user'], name='unique_product_vote')
        # ]
2. 编写投票的视图逻辑

接下来写处理投票请求的视图,这里用函数视图举例,核心逻辑是:验证用户登录状态 → 检查是否已投票 → 未投票则创建记录+更新票数:

from django.shortcuts import get_object_or_404, redirect
from django.contrib.auth.decorators import login_required
from django.contrib import messages
from .models import Product, Vote

@login_required  # 强制用户登录才能投票
def vote_product(request, product_id):
    # 获取要投票的产品,不存在则返回404
    product = get_object_or_404(Product, id=product_id)
    
    # 检查当前用户是否已给该产品投过票,用exists()性能更优
    has_voted = Vote.objects.filter(product=product, user=request.user).exists()
    
    if has_voted:
        messages.error(request, "你已经给这个产品投过票啦,不能重复投票哦!")
        return redirect('product_detail', product_id=product_id)  # 跳回产品详情页
    
    # 未投票则创建投票记录,并更新产品票数
    Vote.objects.create(product=product, user=request.user)
    product.votes_total += 1
    product.save()
    
    messages.success(request, "投票成功!感谢你的支持~")
    return redirect('product_detail', product_id=product_id)
3. 模板中控制投票按钮的显示(可选)

在产品详情页的模板里,你可以根据用户是否已投票,动态调整按钮状态,提升用户体验:

{% if user.is_authenticated %}
    {% if product.votes.filter(user=user).exists %}
        <button class="btn btn-secondary" disabled>已投票</button>
    {% else %}
        <form action="{% url 'vote_product' product.id %}" method="post">
            {% csrf_token %}
            <button type="submit" class="btn btn-primary">投一票</button>
        </form>
    {% endif %}
{% else %}
    <a href="{% url 'login' %}" class="btn btn-outline-primary">登录后投票</a>
{% endif %}
最后补个路由配置

别忘了在项目的urls.py里给投票视图配置路由:

from django.urls import path
from . import views

urlpatterns = [
    # 其他路由...
    path('product/<int:product_id>/vote/', views.vote_product, name='vote_product'),
]

这样一套下来,就能完美实现“用户对单个产品只能投票一次”的功能啦,数据库层面的约束+视图逻辑的检查,双重保障不会出现重复投票的情况。

内容的提问来源于stack exchange,提问作者Hol Seo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 10:06:40