Django 赞成票和反对票系统 [已关闭]

Django upvote & downvote system [closed]

提问人:MickKav 提问时间:10/28/2023 最后编辑:halferMickKav 更新时间:10/30/2023 访问量:36

问:


想改进这个问题吗?通过编辑这篇文章添加详细信息并澄清问题。

25天前关闭。

我正在为我的课程做一个项目,用户可以对项目进行投票。我正在使用 Django,最近才开始学习它。

我在单独单击和激活按钮时遇到了问题,因为我的反对按钮只是激活了赞成票。

我的模板:

 <div class="row">
                    <div class="col-1">
                        <strong>
                            {% if user.is_authenticated %}
                            <form action="{% url 'post_vote' post.slug %}" class="d-inline" method="POST">
                                {% csrf_token %}
                                {% if liked %}
                                <button type="submit" name="blogpost_id" value="{{post.slug}}" id="btn-like" class="btn-like"><i 
                                    class="fa-solid fa-circle-up" style="color: #1ea427;"></i></button>
                                {% else %}
                                <button type="submit" name="blogpost_id" value="{{post.slug}}" id="btn-like" class="btn-like"><i 
                                    class="fa-regular fa-circle-up"></i></button>
                                {% endif %}
                            </form>
                            {% else%}
                            <span class="text-scondary"><i class="fa-regular fa-circle-up"></i></span>
                            {% endif %}
                            <span class="text-secondary">{{ post.number_of_up_votes}}</span>
                        </strong>
                    </div>
                    <div class="col-1">
                        <strong>
                            {% if user.is_authenticated %}
                            <form action="{% url 'post_vote' post.slug %}" class="d-inline" method="POST">
                                {% csrf_token %}
                                {% if disliked %}
                                <button type="submit" name="blogdownpost_id" value="{{post.slug}}" id="btn-like" class="btn-like"><i 
                                    class="fa-solid fa-circle-down" style="color: #ff0000;"></i></button>
                                {% else %}
                                <button type="submit" name="blogdownpost_id" value="{{post.slug}}" id="btn-like" class="btn-like"><i 
                                    class="fa-regular fa-circle-down"></i></button>
                                {% endif %}
                            </form>
                            {% else%}
                            <span class="text-scondary"><i class="fa-regular fa-circle-down"></i></span>
                            {% endif %}
                            <span class="text-secondary">{{ post.number_of_down_votes}}</span>
                        </strong>
                    </div>
                    <div class="col-1">
                        {% with comments.count as total_comments %}
                        <strong class="text-secondary"><i class="far fa-comments"></i>
                            <!-- Our total_comments variable goes before the closing strong tag -->
                            {{ total_comments }}</strong>
                        {% endwith %}
                    </div>
                </div>

我的观点:

from django.shortcuts import render, get_object_or_404, reverse
from django.views import generic, View
from django.http import HttpResponseRedirect
from .models import Post
from .forms import CommentForm


class PostList(generic.ListView):
    model = Post
    queryset = Post.objects.filter(status=1).order_by('-created_on')
    template_name = 'index.html'
    paginate_by = 6


class PostDetail(View):

    def get(self, request, slug, *args, **kwargs):
        queryset = Post.objects.filter(status=1)
        post = get_object_or_404(queryset, slug=slug)
        comments = post.comments.filter(approved=True).order_by('created_on')
        liked = False
        disliked = False
        if post.up_vote.filter(id=self.request.user.id).exists():
            liked = True
        elif post.down_vote.filter(id=self.request.user.id).exists():
            disliked = True

        return render(
            request,
            "post_detail.html",
            {
                "post": post,
                "comments": comments,
                "commented": False,
                "liked": liked,
                "disliked": disliked,
                "comment_form": CommentForm(),
            },
        )
        
    
    def post(self, request, slug, *args, **kwargs):
        queryset = Post.objects.filter(status=1)
        post = get_object_or_404(queryset, slug=slug)
        comments = post.comments.filter(approved=True).order_by('-created_on')
        liked = False
        disliked = False
        if post.up_vote.filter(id=self.request.user.id).exists():
            liked = True
        elif post.down_vote.filter(id=self.request.user.id).exists():
            disliked = True

        comment_form = CommentForm(data=request.POST)

        if comment_form.is_valid():
            comment_form.instance.email = request.user.email
            comment_form.instance.name = request.user.username
            comment = comment_form.save(commit=False)
            comment.post = post
            comment.save()
        else:
            comment_form = CommentForm()
        
        return render(
            request,
            "post_detail.html",
            {
                "post": post,
                "comments": comments,
                "commented": True,
                "liked": liked,
                "disliked": disliked,
                "comment_form": CommentForm(),
            },
        )


class PostVote(View):

    def post(self, request, slug):
        post = get_object_or_404(Post, slug=slug)

        if post.up_vote.filter(id=request.user.id).exists():
            post.up_vote.remove(request.user)
        else:
            post.up_vote.add(request.user)

        if post.down_vote.filter(id=request.user.id).exists():
            post.down_vote.remove(request.user)
        else:
            post.down_vote.add(request.user)

        return HttpResponseRedirect(reverse('post_detail', args=[slug]))

我的模型:

from django.db import models
from django.contrib.auth.models import User
from cloudinary.models import CloudinaryField

STATUS = ((0, "Draft"), (1, "Published"))

class Post(models.Model):
    title = models.CharField(max_length=200, unique=True)
    slug = models.SlugField(max_length=200, unique=True)
    author = models.ForeignKey(User, on_delete=models.CASCADE, related_name="news_posts")
    updated_on = models.DateTimeField(auto_now=True)
    content = models.TextField()
    featured_image = CloudinaryField('image', default='placeholder')
    excerpt = models.TextField(blank=True)
    created_on = models.DateTimeField(auto_now_add=True)
    status = models.IntegerField(choices=STATUS, default=0)
    up_vote = models.ManyToManyField(User, related_name='news_up_vote', blank=True)
    down_vote = models.ManyToManyField(User, related_name='news_down_vote', blank=True)

    class Meta:
        ordering = ['-created_on']

    def __str__(self):
        return self.title

    def number_of_up_votes(self):
        return self.up_vote.count()

    def number_of_down_votes(self):
        return self.down_vote.count()

我试图改变多种方式,如定位和措辞,并观看了许多视频。

python django 模板 project social-likes

评论

0赞 i-wizard 10/30/2023
这里的问题是,在 PostVote 视图调用中,您没有指定用户执行的投票类型(赞成票或反对票)。PostVote 视图逻辑所做的只是在调用视图时切换投票。这个类 PostVote(View) 本质上是 1。如果此人之前投了赞成票,请删除该赞成票,否则添加新的赞成票 2。如果此人之前投了反对票,请删除该反对票,否则添加新的反对票

答:

2赞 i-wizard 10/30/2023 #1

我已经更新了您模板中的赞成表单,以包含一个隐藏字段来表示投票类型

<form action="{% url 'post_vote' post.slug %}" class="d-inline" method="POST">
    {% csrf_token %}
    <input type="hidden" name="vote_type" value="upvote">
    {% if liked %}
    <button type="submit" name="blogpost_id" value="{{post.slug}}" id="btn-like" class="btn-like">
        <i class="fa-solid fa-circle-up" style="color: #1ea427;"></i>
    </button>
    {% else %}
    <button type="submit" name="blogpost_id" value="{{post.slug}}" id="btn-like" class="btn-like">
        <i class="fa-regular fa-circle-up"></i>
    </button>
    {% endif %}
</form>

我还更新了您的反对表,以包含一个隐藏字段来表示投票类型

<form action="{% url 'post_vote' post.slug %}" class="d-inline" method="POST">
    {% csrf_token %}
    <input type="hidden" name="vote_type" value="downvote">
    {% if disliked %}
    <button type="submit" name="blogdownpost_id" value="{{post.slug}}" id="btn-like" class="btn-like">
        <i class="fa-solid fa-circle-down" style="color: #ff0000;"></i>
    </button>
    {% else %}
    <button type="submit" name="blogdownpost_id" value="{{post.slug}}" id="btn-like" class="btn-like">
        <i class="fa-regular fa-circle-down"></i>
    </button>
    {% endif %}
</form>

我已经更新了您的 PostView 类以使用该隐藏 fie 的值

class PostVote(View):
    def post(self, request, slug):
        post = get_object_or_404(Post, slug=slug)

        vote_type = request.POST.get('vote_type', None)
        if vote_type == 'upvote':
            # If the person has not up voted previously then we add a new vote
            post.up_vote.filter(id=request.user.id).exists() is False and post.up_vote.add(request.user)
            
            # If this person previously downvoted this Post then we remove the downvote because because a preson cannot upvote and downvote the same Post
            post.down_vote.filter(id=request.user.id).exists() and post.down_vote.remove(request.user)

        elif vote_type == 'downvote':
            # If the person has not down voted previously then we add a new vote
            post.down_vote.filter(id=request.user.id).exists() is False and post.down_vote.add(request.user)

            # If this person previously upvoted this Post then we remove the upvote because because a preson cannot upvote and downvote the same Post
            post.up_vote.filter(id=request.user.id).exists() and post.up_vote.remove(request.user)

        return HttpResponseRedirect(reverse('post_detail', args=[slug]))

评论

0赞 MickKav 10/30/2023
非常感谢这对我有很大帮助!