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
相关产品推荐
相关产品推荐

