#django #django-models #django-views
#django #django-модели #django-просмотры
Вопрос:
Зарегистрированные в настоящее время пользователи могут повышать голос 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>
Ответ №1:
ну, на вашем месте я бы сделал это так :
#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/>
когда вы закончите, это должно сработать, если здесь не было ошибки, и я дам вам знать, что вы делаете неправильно
Комментарии:
1. И как мне нужно изменить мой views.py ?
2. Как я должен использовать этот класс?
3. Отлично; результаты в той же таблице голосов в базе данных с меньшим количеством кода. Однако для этого нет
blank
параметраManyToManyField
.4. В конце концов, что я должен делать в views.py с помощью этого кода?
5. в ваших представлениях используйте ProductVoteToggle, это перенаправление
Ответ №2:
Ваш код вообще не использует Vote
. В upvote()
сначала попробуйте создать 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')
Комментарии:
1. Насколько я понимаю:
try: Vote.objects.create(user=request.user, product=product) product.votes_total = 1 product.save() except: 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')
Должно быть так?2. Не могли бы вы обновить свой вопрос новым кодом? Это не читается в комментарии.
3. Отлично; хотя вы можете захотеть дифференцировать перенаправление в зависимости от того, было ли голосование успешным. Кроме того, нет необходимости сохранять продукт, если подсчет голосов не изменился.
4. Ошибка: > имя ‘unique_together’ не определено
5. unique_together — это поле в meta:
unique_together = (('user', 'product'),)
. Прошу прощения.