欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

10 实现Django投票的功能

程序员文章站 2024-02-02 12:54:34
...

1、概述

当我们在浏览网站时,经常会碰到如对一篇文章进行投票:喜欢、不喜欢还是弃票。投票也用表单提交实现,但与通常表单不同的是,投票提交的表单不需要进行相关的错误验证。

2、models.py层投票的数据结构

在之前篇章功能的基础上(即models层已有数据Video和用户UserProfile)如下:

class Video(models.Model):
    title = models.CharField(null=True, blank=True, max_length=300)
    content = models.TextField(null=True, blank=True)
    url_image = models.URLField(null=True, blank=True)
    cover = models.FileField(upload_to='cover_image', null=True)
    editors_choice = models.BooleanField(default=False)
    def __str__(self):
        return self.title

class UserProfile(models.Model):
    belong_to = models.OneToOneField(to=User, related_name='profile')
    profile_image = models.FileField(upload_to='profile_image')

解析:以上数据项是实现网页内容和网页登录用户注册设定的。

因投票功能需要将票关联到用户和将票关联到投票对象,这这张票是谁投的,投给那个对象的。故在model层设计票数据项:

class Ticket(models.Model):
    voter = models.ForeignKey(to=UserProfile, related_name='voter_ticket')
    video = models.ForeignKey(to=Video, related_name='video_ticket')
    VOTER_CHICES = (
        ('like','like'),
        ('dislike', 'dislike'),
        ('normal', 'normal'),
    )
    choice = models.CharField(choices=VOTER_CHICES, max_length=10)
    def __str__(self):
        return str(self.id)

解析:

a、字段voter是针对用户的外键,因用户和票是一对多关系,一个用户可以投票多个多项;

b、字段video是这对Video对象的外键,因一个对象可以投多张票,是一对多关系;

c、字段choice是用户的投票选择:喜欢like、不喜欢dislike和未投票normal。

3、投票的网页显示

1)在视图层views.py实现投票显示视图

def detail(request, id):
    context = {}
    vid_info = Video.objects.get(id=id)
    voter_id = request.user.profile.id
    like_counts = Ticket.objects.filter(choice='like',video_id=id).count()
    try:
        user_ticket_for_this_video = Ticket.objects.get(voter_id=voter_id, video_id=id)
        context['user_ticket'] = user_ticket_for_this_video
    except :
        pass
    context['vid_info'] = vid_info
    return render(request, 'detail.html', context)

解析:通过request.user.profile.id来获取当前请求的用户,然后与当前请求对象id结合来获取得到当前的票user_ticket_for_this_video;

2)通过模板来加载变量

<div class="ui basic segment container">
    <h1 class="ui header">{{ vid_info.title }}</h1>
    <i class="icon grey unhide"></i>
    <span style="color:#bbbbbb">10K</span>
    <span class="" style="color:rgb(226, 226, 226)">|</span>
    <i class="icon grey checkmark"></i>
    <span style="color:#bbbbbb">{{ like_counts }} people got it</span> //#01
    <p>
        {{ vid_info.content }}
    </p>
    <div class="ui divider"></div>
    <form class="ui form" action="" method="post">
        {% csrf_token %}
        {% if user_ticket.choice == 'like' %} //#02
            <button class="ui red tiny button" type="submit" name="vote" value="normal">
                <i class="icon checkmark"></i>
                Get it!
            </button>

            <button class="ui tiny button" type="submit" name="vote" value="dislike">
                <i class="icon bomb"></i>
                Hmmm...
            </button>
        {% elif user_ticket.choice == 'dislike' %}
            <button class="ui tiny button" type="submit" name="vote" value="like">
                <i class="icon checkmark"></i>
                Get it!
            </button>

            <button class="ui red tiny button" type="submit" name="vote" value="normal">
                <i class="icon bomb"></i>
                Hmmm...
            </button>
        {% else %}
            <button class="ui tiny button" type="submit" name="vote" value="like">
                <i class="icon checkmark"></i>
                Get it!
            </button>

            <button class="ui tiny button" type="submit" name="vote" value="dislike">
                <i class="icon bomb"></i>
                Hmmm...
            </button>

            <button class="ui secondary circular tiny right floated pin icon button">
                <i class="pin icon"></i>
                Saved
            </button>
        {% endif %}
    </form>
</div>
解析:

a、#01通过对Ticket数据进行过滤计算获取对当前对象的投票总数;

b、#02通过if判断当前登录用户对登录对象的状态判断,来显示投票状态,网页显示如下:

10 实现Django投票的功能

3、投票的结果存储功能

如上只是显示了在后台对Ticket进行操作后,网页中的投票状态的显示结果。下面将是直接在网页中进行投票,如用户点击投票则结果保存至数据库状态。

1)在views.py层添加投票视图

from  django.core.exceptions import ObjectDoesNotExist

def detail_vote(request, id):
    voter_id = request.user.profile.id
    try:
        user_ticket_for_this_video = Ticket.objects.get(voter_id=voter_id, video_id=id)
        user_ticket_for_this_video.choice = request.POST['vote']
        user_ticket_for_this_video.save()
    except ObjectDoesNotExist:
        new_ticket = Ticket(voter_id=voter_id, video_id=id, choice=request.POST['vote'])
        new_ticket.save()
    return redirect(to='detail', id=id)

解析:视图的逻辑是如果当前用户票已存在,则点击提交的状态进行修改保存;如果用户的票不存在,则根据提交结果新创建一张用户票。

2)在urls.py层增加投票视图

    url(r'^detail/(?P<id>\d+)$', detail, name='detail'),
    url(r'^detail/vote/(?P<id>\d+)$', detail_vote, name='vote'),
3)在模板层增加投票结果跳转

<form class="ui form" action="{% url 'vote' vid_info.id %}" method="post">
    ...
</form>

说明:action中内容即在点击投票结果的时候,会进行视图跳转。