Джанго - Как сделать кнопку upvote? - PullRequest
0 голосов
/ 14 марта 2019

В настоящее время вошедшие в систему пользователи могут проголосовать x раз. Идея исправить это заключается в создании новой модели под названием Голосование. И это будет иметь иностранные клавиши для пользователя и продукта. Когда кто-то идет на голосование, вы проверяете и видите: есть ли объект голосования с этим идентификатором пользователя и идентификатором продукта, и если он есть, вы не разрешите ему снова поднять голос; и если это не так, то вы можете создать его и просто увеличить total_votes на единицу. Но на самом деле я столкнулся с этим и не могу понять это и решить.

Итак, есть мой models.py

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

class Product(models.Model):
    title = models.CharField(max_length=255)
    pub_date = models.DateTimeField()
    body = models.TextField()
    url = models.TextField()
    image = models.ImageField(upload_to='images/')
    icon = models.ImageField(upload_to='images/')
    votes_total = models.IntegerField(default=1)
    hunter = models.ForeignKey(User, on_delete=models.CASCADE)

def __str__(self):
    return self.title

def summary(self):
    return self.body[:100]

def pub_date_pretty(self):
    return self.pub_date.strftime('%b %e %Y')

class Vote(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    voteproduct = models.ForeignKey(Product, on_delete=models.CASCADE)

И мои views.py

from django.shortcuts import render, redirect, get_object_or_404
from django.contrib.auth.decorators import login_required
from .models import Product, Vote
from django.utils import timezone

@login_required(login_url="/accounts/signup")
def upvote(request, product_id):
    if request.method == 'POST':
         product = get_object_or_404(Product, pk=product_id)
         product.votes_total += 1
         product.save()
         return redirect('/products/' + str(product.id))

Обновление:

class Vote(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
product = models.ForeignKey(Product, on_delete=models.CASCADE)

class Meta:
    unique_together(('user', 'product'),)

views.py

if request.method == 'POST':
    product = get_object_or_404(Product, pk=product_id)
    try:
        Vote.objects.create(user=request.user, product=product)
        product.votes_total += 1
        product.save()
    except:
        product.save()
    return redirect('/products/' + str(product.id))

Кроме того, как мне изменить мой файл .html? Я действительно не могу понять, что происходит. Будем рады услышать от вас.

{% for product in products.all %}
<div class="row pt-3">
<div class="col-2" onclick="window.location='{% url 'detail' product.id 
                                        %}';" style="cursor: pointer;">
<img src="{{ product.icon.url }}" class="img-fluid" />
</div>
<div class="col-7" onclick="window.location='{% url 'detail' product.id 
                                        %}';" style="cursor: pointer;">
<h1>{{ product.title }}</h1>
<p>{{ product.summary }}</p>
</div>
<div class="col-3">
    <a href="javascript:{document.getElementById('{% url 'upvote' 
    product.id %}').submit()}"><button class="btn btn-primary btn-lg btn- 
    block" name="btn1" value="upvote"><span class="oi oi-caret-top"> 
    </span> Upvote {{ product.votes_total }}</button></a>
</div>
</div>

<form id="get_redirect_url{{ product.id }}" action="{% url 'upvote' 
object.id %}" method="POST">
{% csrf_token %}
<input type="hidden" />
</form>

Ответы [ 2 ]

1 голос
/ 14 марта 2019

ну, если бы я был тобой, я бы сделал это так:

#step 1  change votes_total from integerfield to manytomany field 
##models
class Product(models.Model):
    #other fields goes here
    votes_total = models.ManyToManyField(User, related_name="votes" ,)

#step 2 ; go to your views.py and copy paste the following :

from django.views.generic import RedirectView


class ProductVoteToggle(RedirectView):

    def get_redirect_url(self, *args ,**kwargs):

        obj = get_object_or_404(Product, pk=self.kwargs['pk'])
        url_ = obj.get_absolute_url() 
        user = self.request.user
        if user.is_authenticated():
            if user in obj.votes_total.all():
                # you could remove the user if double upvote or display a message or what ever you want here
                obj.votes_total.remove(user)
            else:
                obj.votes_total.add(user)

        return url_


   #step 3 : go to urls.py and paste add the following : 
    urlpatterns = [
        #other urls here
        path('vote/<int:pk>',ProductVoteToggle.as_view() , name="upvote"),
]
     #in your template remove that form and paste the following code : 
     <a href="{% url 'upvote' product.id %}>Click to vote<a/>

когда вы закончите, это должно сработать, если ошибка не исчезла, и я сообщу вам, что вы делаете неправильно

0 голосов
/ 14 марта 2019

Ваш код вообще не использует Voteupvote() сначала попытайтесь создать Vote для пользователя и продукта:

try:
    Vote.objects.create(user=request.user, product=product)
    # consider using the name product instead of voteproduct

В случае успеха увеличьте счетчик.Если это не удается, сообщите пользователю, что он уже проголосовал.

Очевидно, вам необходимо уникальное ограничение в Vote:

class Meta:
    unique_together = ('user', 'product')
...