投票系统
创建基本模型
投票系统,我们必须要建立的两个基本模型就是投票人(用户,下文我统一用“用户”)和被投票人,话不多说,先上代码:
1:被投票人的基本模型
class Person(models.Model):
name = models.CharField(max_length=30)
ballot = models.FloatField(default=0, max_length=30, null=False)
sex = models.CharField(max_length=30)
Class = models.CharField(max_length=30)
major = models.CharField(max_length=30)
grade = models.CharField(max_length=30)
story = models.TextField()
img_url = models.CharField(max_length=150, null=True)
def __str__(self):
return f"{self.name} - {self.Class} - {self.ballot} - {self.sex}"
2:用户
用户名和密码我们可以直接可以继承User类,其余字段自己定义
class userform(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
nickname = models.CharField(blank=True, max_length=50)
phonenumber = models.CharField(blank=True, max_length=20)
banji = models.CharField(blank=True, max_length=20)
xuehao = models.CharField(blank=True, max_length=20)
count = models.FloatField(default=0, blank=True, max_length=50)
img_url = models.CharField(max_length=150, null=True)
class Meta:
verbose_name_plural = "userform"
或许作为刚入手django的新手来说,做这样的投票系统会有以下想法:在views中定义一个vote方法,获取当前用户和被投票人,检查用户的count字段是否小于5(投票限制),若是,则被投票人的ballot字段加一,保存,这样虽然也可以实现简单的邮票限制,不过方法很死,不容易进行拓展。 代码如下,代码中那几个int,str的转换是因为我一开始定义的字段类型是CharField
def vote(request, id):
obj = models.Person.objects.get(id=id)
user = request.user
user_count = user.userform.count
user_count = int(user_count)
if user_count < 5:
user.userform.count = int(user.userform.count) + 1
user.userform.count = str(user.userform.count)
user.userform.save()
piao = int(obj.ballot) + 1
obj.ballot = piao
obj.save()
url = reverse('showall')
return HttpResponse(f'<script>alert("投票成功");location.href="' + url + '";</script>')
else:
url = reverse('showall')
return HttpResponse(f'<script>alert("每人只能投五票!");location.href="' + url + '";</script>')
接下来我们继续,淘汰上述方法,继续淦。
我们可以在models里面再建一个模型,建一个用户和被投票人的中间模型,来记录每一次投票记录
class VotesRecord(models.Model):
voted_person = models.ForeignKey("Person", on_delete=models.DO_NOTHING)
voting_person = models.ForeignKey("userform", on_delete=models.DO_NOTHING)
vote_datetime = models.DateTimeField()
def __str__(self):
return f"{self.voted_person.name} - {self.voting_person.nickname} - {self.vote_datetime}"
模型方法的构建
在该中间模型中,我们额外定义了投票时间这个字段,这样我们就可以对投票限制进行扩展,比如一天可以投5票,哪个时间段有多少限制,可以自由发挥。 定义好上述3个模型我们就可以写我们的投票方法,不过,如果将全部的代码都写在views中并不是一件好事,我们最好在模型中先写好模型方法,这样只用在views中写我们的逻辑判断,然后执行不同的方法即可。Let’s go 首先,在userform即我们的用户模型中添加vote方法
class userform(models.Model):
def vote(self, voted_person: Person):
new_record = VotesRecord()
new_record.voted_person = voted_person
new_record.voting_person = self
new_record.vote_datetime = datetime.datetime.now()
new_record.save()
self.count += 1
voted_person.ballot += 1
self.save()
voted_person.save()
return new_record
这样,我们就完成了投票方法的书写。
接下来我们写投票限制条件的方法。
在userform即我们的用户模型中添加vote_data方法,用来检查当前用户的投票数
class userform(models.Model):
def vote_data(self, today=False):
if today:
current_datetime = datetime.datetime.now()
return self.votesrecord_set.filter(voting_person=self,
vote_datetime__year=current_datetime.year,
vote_datetime__month=current_datetime.month,
vote_datetime__day=current_datetime.day)
else:
return self.votesrecord_set.filter(voting_person=self)
这样,我们在调用该方法的时候,只需要令today=True 即可获取到当前用户所有的投票纪录,然后用count()方法即可知道当前用户今日偷的总票数。代码中用到的votesrecord_set如果不懂可以去看看django官方文档对于中间模型的介绍。应该在多对多关系里面有所介绍 多对多关系
通过以上,我们就可以实现一天之内一个用户最多可以投多少票,这样的方法比博客开头的方法显然更优,而且可以在django的后台查看投票纪录 投票纪录也可以在数据库中查看。 做到这里其实已经不错了,但是我们可以继续稍微拓展一下,限制每位用户每天不能给同一用户投超过3票,如果可以理解上面的方法,那么这个功能添加起来也不是什么难事。
我们在views中用以下方法得到当前用户今日一共给被投票人的投票纪录
vote_records2: QuerySet = user.votesrecord_set.filter(voted_person = voted_person,vote_datetime__year=current_datetime.year,
vote_datetime__month=current_datetime.month,
vote_datetime__day=current_datetime.day)
然后通过count()方法得到数量
##views中书写逻辑
def vote(request, id):
voted_person = models.Person.objects.get(id=id)
user = request.user.userform
current_datetime = datetime.datetime.now()
vote_records2: QuerySet = user.votesrecord_set.filter(voted_person = voted_person,vote_datetime__year=current_datetime.year,
vote_datetime__month=current_datetime.month,
vote_datetime__day=current_datetime.day)
vote_records: QuerySet = user.vote_data(today=True)
user_count2 = vote_records2.count()
user_count = vote_records.count()
if user_count2 >= 3 :
url = reverse('showall')
return HttpResponse(f'<script>alert("您每天最多给同一个人投三票");location.href="' + url + '";</script>')
if user_count < 5:
new_record = user.vote(voted_person)
url = reverse('showall')
return HttpResponse(f'<script>alert("投票成功");location.href="' + url + '";</script>')
else:
url = reverse('showall')
return HttpResponse(f'<script>alert("您每天最多投5票");location.href="' + url + '";</script>')
解释一下那个id 这是我的前端页面 下面是部分代码
<th>
{% if request.user.is_superuser %}
<a href="{% url 'deleteperson' i.id %}">删除</a>
<a href="{% url 'changeperson' %}?id={{ i.id }}">修改</a>
{% endif %}
<a href="{% url 'vote' i.id %}">投票</a>
</th>```
点击投票,页面会传来你要投的对象的Id.
还有,url里面也要加上/int:id,表示接受一个int类型参数
path('vote/<int:id>', views.vote, name="vote"),
结尾
到这里有关投票的相关已经介绍完了,通过写这个小系统也学到了不少东西,当然,并没有把整个系统完全进行介绍,还有用户的注册,登录,提名,排行榜这些东西,不过通过投票这几个模型的构建,其他功能也不是很麻烦了,有兴趣的小伙伴可以在此基础上继续做哦!如果接下来有时间,可以把剩余的内容也进行分享。
|