ValueError Cannot assign "<QuerySet [<Product:name>] - python

I am a student learning Django. I want to implement so that I receive the product code in the order(join model) DB when ordering a product, but it is difficult because I keep getting an error like the title. I think I will die because it hasn't been solved for too long.
When I use product.object.all(), all the query sets are loaded, and even when I use a filter, an error occurs. How can I solve this problem? It would be such an honor if you could reply.
Error Message
ValueError at /join/element_detail/ Cannot assign "<QuerySet
[<Product: 학잠>, <Product: 헤라 블랙쿠션>, <Product: 종근당 활력 비타민B>, <Product:
코디 순수 3겹데코>, <Product: 다이어리>, <Product: 화이트 스탠드 조명>, <Product: 파이썬 웹
프로그래밍 교재>, <Product: 나이키 후드집업>]>": "Join.product_code" must be a
"Product" instance.
join / views.py
join.product_code = product
This part appears to be the problem.
models.py
class Product(models.Model):
product_code = models.AutoField(primary_key=True)
username = models.ForeignKey(Member, on_delete=models.CASCADE, db_column='username')
category_code = models.ForeignKey(Category, on_delete=models.SET_NULL, null=True, related_name='products')
name = models.CharField(max_length=200, db_index=True)
slug = models.SlugField(max_length=200, db_index=True, unique=False, allow_unicode=True)
image = models.ImageField(upload_to='products/%Y/%m/%d', blank=True)
benefit = models.TextField()
detail = models.TextField()
target_price = models.IntegerField()
start_date = models.DateField()
due_date = models.DateField()
class Meta:
ordering = ['product_code']
index_together = [['product_code', 'slug']]
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('zeronine:product_detail', args=[self.product_code, self.slug])
class Join(models.Model):
join_code = models.AutoField(primary_key=True)
username = models.ForeignKey(Member, on_delete=models.CASCADE, db_column='username')
product_code = models.ForeignKey(Product, on_delete=models.CASCADE, db_column='product_code')
part_date = models.DateTimeField(auto_now_add=True)
def __str__(self):
return str(self.join_code)
class Meta:
ordering = ['join_code']
My guess is that there is something wrong with this part.(join/views.py)
I think something went wrong in the process of receiving the product, but I don't know how.
join/views.py
def element_detail(request):
designated_object = Designated.objects.all()
element_object = Element.objects.all()
value_object = Value.objects.all()
product = Product.objects.all()
if request.method == "POST":
join = Join()
join.product_code = product
join.username = request.user
join.part_date = timezone.now()
join.save()
return render(request, 'zeronine/list.html')
return render(request, 'zeronine/detail.html', {'designated_object': designated_object,
'element_object': element_object,
'value_object': value_object})
zeronine/views.py
def product_in_category(request, category_slug=None):
current_category = None
categories = Category.objects.all()
products = Product.objects.all()
if category_slug:
current_category = get_object_or_404(Category, slug=category_slug)
products = products.filter(category_code=current_category)
return render(request, 'zeronine/list.html', {'current_category': current_category,
'categories':categories,
'products':products})
def product_detail(request, id, product_slug=None):
current_category = None
categories = Category.objects.all()
products = Product.objects.all()
product = get_object_or_404(Product, product_code=id, slug=product_slug)
designated_object = Designated.objects.filter(rep_price='True')
element_object = Element.objects.all()
value_object = Value.objects.all()
return render(request, 'zeronine/detail.html', {'product':product,
'products':products,
'current_category': current_category,
'categories':categories,
'designated_object': designated_object,
'element_object':element_object,
'value_object':value_object})
zeronine/detail.html
<form method="POST" style="margin-left: 110px;" action="{% url 'zeronine:element_detail' %}">
<div class="form-group row">
<label for="value_code" class="col-sm-2 col-form-label"><b>옵션</b></label>
<div class="col-sm-5">
<select type="text" class="form-control" name="value_code" id="value_code">
{% for value in value_object %}
{%if value.product_code == product %}
<option value="{{value.value_code}}">{{value.name}}</option>
{% endif %}
{% endfor %}
</select>
</div>
</div>
{% csrf_token %}
{% if not user.is_authenticated %}
<a onclick="alert('로그인 후 참여가 가능합니다.');" style="cursor:pointer;">
<button type="submit" style="background:black; border-color:black;" class="btn btn-primary"> 참여하기</button></a>
<a onclick="alert('로그인 후 찜하기가 가능합니다.');" style="cursor:pointer;">
<button type="submit" style="background:white; color:black; border-color:black;" class="btn btn-primary">찜하기</button></a>
{% else %}
<a onclick="alert('{{ product.name }} 공동구매 참여가 완료되었습니다.');" style="cursor:pointer;">
<button type="submit" action="{% url 'zeronine:element_detail' %}" style="background:black; border-color:black;" class="btn btn-primary"> 참여하기</button></a>
<a onclick="alert('{{ product.name }} 상품을 찜했습니다.');" style="cursor:pointer;">
<button type="submit" style="background:white; color:black; border-color:black;" class="btn btn-primary">찜하기</button></a>
{% endif %}
</form>

def element_detail(request):
designated_object = Designated.objects.all()
element_object = Element.objects.all()
value_object = Value.objects.all()
product = Product.objects.all()
if request.method == "POST":
product_id = request.POST.get('value_code') # new
product = Product.objects.get(product_code=product_id) # new
# Or
#product_ids = request.POST.getlist('value_code')
#products = Product.objects.filter(product_code__in=product_ids)
#loop all products and save example;
#for product in products:
# join = Join()
# join.product_code = product
# join.username = request.user
# join.part_date = timezone.now()
# join.save()
join = Join()
join.product_code = product
join.username = request.user
join.part_date = timezone.now()
join.save()
return render(request, 'zeronine/list.html')
Edited to include multiple values from template, I'm assuming of course.

Related

How to get highest bid in an auction bidding site Django

So I have a Django auctions app, which has 3 models: Users, Listings, Bids.
When a user tries to place a bid on some listing, I want to check if the new_bid field in Bid model is bigger than start current_bid field in Listing model and if the new_bid is <= 0, it should return a message.
This is what I've done so far but when I click on 'Place bid' button, it does not implement this, the page doesn't redirect to an error page if the value is less than the current bid and doesn't update the bid if the user adds another one.
Why is this not working?
VIEWS.PY
def listing_detail(request, listing_id):
try:
detail = get_object_or_404(Auction, pk=listing_id)
except Auction.DoesNotExist:
messages.add_message(request, messages.ERROR, "This is not available")
return HttpResponseRedirect(reverse("index"))
bid_count = Bids.objects.filter(auction=listing_id).count()
context = {'detail': detail, 'bid_count': bid_count, 'bidForm': BidForm()}
return render(request, 'auctions/details.html', context)
#login_required
def make_bid(request, listing_id):
if request.method == 'POST':
form = BidForm(request.POST)
if form.is_valid:
each_listing = Auction.objects.get(pk=listing_id)
highest_bid = Bids.objects.filter(pk=listing_id).order_by('-new_bid').first()
new_bid = form.cleaned_data.get['new_bid']
if new_bid <= 0:
return render(request, 'auctions/details.html',
{"message": "Input an amount greater than 0"})
# messages.add_message(request, messages.SUCCESS, "Input an amount greater than 0")
elif new_bid <= highest_bid.new_bid:
messages.add_message(request, messages.ERROR, "Amount is low, please increase the bid")
else:
highest_bid = Bids(each_listing=each_listing, user=request.user, new_bid=new_bid)
highest_bid.save()
each_listing.current_bid = new_bid
each_listing.save()
return HttpResponseRedirect(reverse("index"))
messages.add_message(request, messages.SUCCESS, "Your bid is currently the highest")
else:
form = BidForm()
return render(request, 'auctions/details.html', {'bidForm': form})
else:
form = BidForm()
return render(request, 'auctions/details.html', {'bidForm': form})
MODELS.PY
class User(AbstractUser):
pass
class Auction(models.Model):
title = models.CharField(max_length=25)
description = models.TextField()
current_bid = models.IntegerField(null=False, blank=False)
image_url = models.URLField(verbose_name="URL", max_length=255, unique=True, null=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
class Meta:
ordering = ['-created_at']
class Bids(models.Model):
auction = models.ForeignKey(Auction, on_delete=models.CASCADE, related_name='bidding')
user = models.ForeignKey(User, on_delete=models.PROTECT, related_name='bidding')
new_bid = models.DecimalField(max_digits=8, decimal_places=2)
# new_bid = MoneyField(max_digits=10, decimal_places=2, null=False, blank=False, default_currency='USD')
done_at = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ['auction', '-new_bid']
FORMS.PY
class AuctionForm(forms.ModelForm):
class Meta:
model = Auction
fields = ['title', 'description', 'current_bid', 'image_url', 'category']
class BidForm(forms.ModelForm):
class Meta:
model = Bids
fields = ['new_bid']
labels = {
'new_bid': ('Choose your maximum bid'),
}
DETAILS.HTML
<div class="row container">
<div class="col-sm-7 pr-5">
{% if detail.image_url %}
<img src='{{ detail.image_url }}' alt="{{ detail.title }}" style="width:100%">
{% else %}
<img src="https://demofree.sirv.com/nope-not-here.jpg">
{% endif %}
</div>
<div class="col-sm-5">
<div style="width: 30rem;">
<div>
<h5>{{ detail.title }}</h5>
<hr>
<p>{{ detail.description }}</p>
<hr>
<p>${{ detail.current_bid }}</p>
<p>{{ bid_count }}</p>
<hr>
<form action="{% url 'listing_detail' detail.id %}" method="post">
{% csrf_token %}
{{ bidForm }}
<input type="submit" class="btn btn-primary btn-block mt-3" value="Place bid">
</form>
<button class="btn-block btn-outline-primary mt-3">Add to watchlist</button>
</div>
</div>
</div>

I want to create a details page with two models for an auction site with django but keep getting FieldError. How do I correct this error?

I am creating an ebay like aunction site, the details view page should reflect details from two models.
One of the models has the details of the current_bid (this is created when creating the listing), there is also the second model that contains new_bids (this is where the users who want to purchase the item can input their bids).
The issue(s) I'm having is how to put two models in my details view and also if you can confirm my current logic in finding out the highest bid (if this is correct or not).
MODELS.PY
class Auction(models.Model):
ABSTRACT = 'AB'
MODERN = 'MN'
ILLUSTRATION = 'IN'
select_category = [
('ABSTRACT', 'Abstract'),
('MODERN', 'Modern'),
('ILLUSTRATION', 'Illustration')
]
title = models.CharField(max_length=25)
description = models.TextField()
current_bid = models.IntegerField(null=False, blank=False)
image_url = models.URLField(verbose_name="URL", max_length=255, unique=True, null=True, blank=True)
category = models.CharField(
choices=select_category,
max_length=12,
default=MODERN,
null=True, blank=True
)
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
class Meta:
ordering = ['-created_at']
class Bids(models.Model):
auction = models.ForeignKey(Auction, on_delete=models.CASCADE, related_name='bidding')
user = models.ForeignKey(User, on_delete=models.PROTECT, related_name='bidding')
new_bid = models.DecimalField(max_digits=8, decimal_places=2)
# new_bid = MoneyField(max_digits=10, decimal_places=2, null=False, blank=False, default_currency='USD', default=0)
done_at = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ['auction', '-new_bid']
FORMS.PY
class AuctionForm(forms.ModelForm):
class Meta:
model = Auction
fields = ['title', 'description', 'current_bid', 'image_url', 'category']
class BidForm(forms.ModelForm):
class Meta:
model = Bids
fields = ['new_bid']
labels = {
'new_bid': ('Choose your maximum bid'),
}
VIEWS.PY
def listing_detail(request, listing_id):
detail = get_object_or_404(Auction, pk=listing_id)
if detail == None:
messages.add_message(request, messages.ERROR, "This is not available")
return HttpResponseRedirect(reverse("index"))
bid_queryset = Bids.objects.filter(detail=listing_id).order_by('new_bid').first()
if bid_queryset == None:
bid = detail.current_bid
else:
bid = bid_queryset.new_bid
context = {'detail': detail}
return render(request, 'auctions/details.html', context)
#login_required
def make_bid(request, listing_id):
bid_item = get_object_or_404(Bids, pk=listing_id)
each_listing = Auction.objects.get(pk=listing_id)
try:
highest_bid = each_listing.bidding.order_by('-new_bid')[0]
except Bids.DoesNotExist:
highest_bid = 0
if request.method == 'POST':
form = BidForm(request.POST)
if form.is_valid:
if form['bidding'] > highest_bid:
bidding = form.save()
messages.add_message(request, messages.SUCCESS, "Your bid is currently the highest")
return HttpResponseRedirect(reverse("index"))
else:
messages.add_message(request, messages.ERROR, "Your bid must be higher than the previous bid")
else:
form = BidForm(initial={'each_listing': each_listing,
'user': request.user,
'amount': highest_bid})
return render(request, 'auctions/details.html', {'form': form})
DETAILS.HTML
<section>
<div class="row container">
<div class="col-sm-7 pr-5">
{% if detail.image_url %}
<img src='{{ detail.image_url }}' alt="{{ detail.title }}" style="width:100%">
{% else %}
<img src="https://demofree.sirv.com/nope-not-here.jpg">
{% endif %}
</div>
<div class="col-sm-5">
<div style="width: 30rem;">
<div>
<h5>{{ detail.title }}</h5>
<hr>
<p>{{ detail.description }}</p>
<hr>
<p>{{ detail.current_bid }}</p>
<hr>
<p>{{ detail.new_bid }}</p>
<hr>
<button class="btn btn-primary btn-block" >Place bid</button>
<button class="btn-block btn-outline-primary">Add to watchlist</button>
</div>
</div>
</div>
<form action="{% url 'auctions:listing_detail' listing.id %}" method="post">
{% csrf_token %}
{{form.as_p}}
<input type="submit" value="Submit">
</form>
Right now, I'm having this error message
FieldError at /detail/15/
Cannot resolve keyword 'detail' into field. Choices are: auction, auction_id, done_at, id, new_bid, user, user_id
Traceback Switch to copy-and-paste view
C:\Users\USER\AppData\Local\Programs\Python\Python310\lib\site-packages\django\core\handlers\exception.py, line 47, in inner
response = get_response(request) …
Local vars
C:\Users\USER\AppData\Local\Programs\Python\Python310\lib\site-packages\django\core\handlers\base.py, line 181, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs) …
Local vars
C:\Users\USER\Downloads\commerce\commerce\auctions\views.py, line 95, in listing_detail
bid_queryset = Bids.objects.filter(detail=listing_id).order_by('new_bid').first()
URLS.PY
urlpatterns = [
path("", views.index, name="index"),
path("create/", views.create_listing, name="create_listing"),
path("detail/<int:listing_id>/", views.listing_detail, name="listing_detail"),
path("bid/<int:listing_id>/", views.make_bid, name="bid"),
Either you should add pk or id field in listing_detail view
Try this :
def listing_detail(request, listing_id):
detail = get_object_or_404(Auction, pk=listing_id)
if detail == None:
messages.add_message(request, messages.ERROR, "This is not available")
return HttpResponseRedirect(reverse("index"))
bid_queryset = Bids.objects.filter(pk=listing_id).order_by('new_bid').first() # change here
if bid_queryset == None:
bid = detail.current_bid
else:
bid = bid_queryset.new_bid
Note :
Change this {% url 'auctions:bid' listing.id %} to {% url 'bid' listing.id %}
make sure that listing.id is from template variables.

Django 5 star rating system is not saving reviews and rating

I build a model for user reviews and rating. And made the form for my model , then I call the form in my views . When i click on button from detail page to get the "rate.html" it get me there but did not save the data from there and give me this error .
IntegrityError at /product/new-shoes/rate/
NOT NULL constraint failed: products_review.user_id
my models.py is:
class Review(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
product = models.ForeignKey(Product , on_delete=models.CASCADE)
date = models.DateTimeField(auto_now_add=True)
text = models.TextField(max_length=3000 , blank=True)
rate = models.PositiveSmallIntegerField(choices=RATE_CHOICES)
likes= models.PositiveIntegerField(default=0)
dislikes = models.PositiveIntegerField(default=0)
def __str__(self):
return self.user.full_name
my forms.py is:
class RateForm(forms.ModelForm):
text = forms.CharField(widget=forms.Textarea(attrs={'class':'materialize-textarea'}),required=False)
rate = forms.ChoiceField(choices=RATE_CHOICES, widget=forms.Select(),required=True)
class Meta:
model = Review
fields= ('text', 'rate')
my views.py is:
class RateView(CreateView):
form_class = RateForm
template_name = 'rate.html'
def form_valid(self, form):
form.instance.product = Product.objects.get(slug=self.kwargs['slug'])
return super().form_valid(form)
def get_success_url(self):
return reverse('products:detail', kwargs={'slug': self.object.product.slug})
and my rate.html is:
{% extends "base.html"%}
{% block content %}
<form method="POST" action="" role="form" class="col s12">
{% csrf_token %}
<div class="input-field col s12">
{{ form.rate }}
</div>
<div class="input-field col s12">
{{ form.text }}
<label for="textarea1">Opinion</label>
</div>
<button type="submit" name="action" class="waves-effect waves-light btn"><i class="material-icons left">star</i>Rate</button>
</form>
{% endblock %}
my urls.py for the view is:
path('<slug:slug>/rate/', RateView.as_view(), name='rate-product1'),
The error message is telling you that the user field is not being set. You can do this in the form_valid function:
def form_valid(self, form):
...
form.instance.user = self.request.user
form.instance.product = Product.objects.get(slug=self.kwargs['slug'])
...
return super().form_valid(form)
Try to use this :-
class Review(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
product = models.ForeignKey(Product , on_delete=models.CASCADE,null=True)
date = models.DateTimeField(auto_now_add=True)
text = models.TextField(max_length=3000 , blank=True)
rate = models.PositiveSmallIntegerField(choices=RATE_CHOICES)
likes= models.PositiveIntegerField(default=0)
dislikes = models.PositiveIntegerField(default=0)
def __str__(self):
return self.user.full_name
What i have changed :-
I have set null = True in your product variable, which is with ForeignKey

django combine multiple ListView using get_query and search form

in my project, I have three models
models.py
class Category(models.Model):
name = models.CharField(max_length=50)
slug = models.SlugField(max_length=50, unique=True, null=True, blank=True)
parent = models.ForeignKey('self', on_delete=models.CASCADE, blank=True, null=True, related_name='children')
class Tag(models.Model):
tag = models.CharField(max_length=75, verbose_name='Tag')
slug = models.SlugField(null=True)
class Post(models.Model):
title = models.CharField(max_length=150)
slug = models.SlugField(max_length=150, null=True, blank=True)
category = models.ForeignKey(Category, on_delete=models.CASCADE, null=True)
tags = models.ManyToManyField(Tag, related_name='tags', blank=True)
and I created search filter view in views.py
def is_valid_queryparam(param):
return param != '' and param is not None
class SearchPepsiView(ListView):
template_name = "blog/NewSearch.html"
model = Post
paginate_by = 10
def get_queryset(self):
return Post.objects.filter(category__slug=self.kwargs['slug'])
def get_context_data(self, *args, **kwargs):
context = super(SearchPepsiView, self).get_context_data(*args, **kwargs)
context['category'] = Post.objects.filter(category__slug=self.kwargs['category'])
return context
def get(self, request, *args, **kwargs):
request = self.request
qs = Post.objects.all()
categories = Category.objects.filter(parent=None).order_by('name')
PostOrAuthor_query = request.GET.get('PostOrAuthor')
SearchCategory_query = request.GET.get('SearchCategory')
if is_valid_queryparam(PostOrAuthor_query):
qs = qs.filter(Q(title__icontains=PostOrAuthor_query) |
Q(content__icontains=PostOrAuthor_query) |
Q(author__username__icontains=PostOrAuthor_query)).distinct()
if is_valid_queryparam(SearchCategory_query) and SearchCategory_query != 'Choose...':
qs = qs.filter(category__name=SearchCategory_query)
count = qs.count() or 0
return render(request, self.template_name, {
'queryset': qs,
'categories': categories,
'count': count,
})
and I created Post Per Category View in views.py
class PostPerCategoryCBV(ListView):
model = Post
template_name = 'blog/Category_Projects.html'
def get_queryset(self):
self.category = Category.objects.get(slug=self.kwargs['slug'])
return Post.objects.filter(category=self.category)
def get_context_data(self, **kwargs):
context = super(PostPerCategoryCBV, self).get_context_data(**kwargs)
context['category'] = self.category
return context
and I created Post Per Tag View in views.py
class PostPerTagCBV(ListView):
model = Post
template_name = 'blog/tag_projects.html'
def get_queryset(self):
qs = super().get_queryset()
qs = qs.filter(tags__slug=self.kwargs['slug'])
return qs
and in templates, I created NewSearch.html
<form class="col-12 mt-5 mb-5">
<div class="form-group">
<label for="formGroupExampleInput">Post or Author</label>
<input type="search" name="PostOrAuthor" class="form-control" id="inputAddress" placeholder="Post or Author">
</div>
<div class="form-row">
<div class="form-group col-md-12">
<label for="SearchCategory">Category</label>
<select id="SearchCategory" name="SearchCategory" class="form-control">
<option selected>Choose...</option>
{% for cat in categories %}
<option value="{{ cat.name }}">{{ cat.name }}</option>
{% endfor %}
</select>
</div>
</div>
<button type="submit" class="btn btn-primary col-12">Search</button>
</form>
</div>
<div class="row">
<p>You have<b> {{ count }} </b>search results </p>
</div>
{% if category %}
<div class="row">
{% for post in category %}
{% include 'blog/Post_Loop.html' %}
{% endfor %}
</div>
{% else %}
<div class="row">
{% for post in queryset %}
{% include 'blog/Post_Loop.html' %}
{% endfor %}
</div>
{% endif %}
</div>
and Here is my URLs.py
path('post_list/', PostListCBV.as_view(), name='list-post'),
path("search-pepsi/", SearchPepsiView.as_view(), name="search-pepsi"),
path('tags_projects/<str:slug>/', PostPerTagCBV.as_view(), name='tag-posts'),
path('category_posts/<str:slug>/', SearchPepsiView.as_view(), name='category-posts'),
My success:
When all search fields are empty .. it list all posts.
when entering any search query .. it backs with the search result.
my problem is:
I believe that there are someway I can combine ListView of Post_Per_Category and Post_Per_Tag with Search View (in ONE View and one template) .. so I created def get_queryset(self): to use it but it didn't worked.
Anybody can help please ...
Thanks in-advance

how to change vote into voted after user votes the choices?

This Code is working perfectly. The only thing I want to change is submit button "Vote" into "Voted" after user voted the option ,instead of displaying error message " You Already Voted".So that the user can know which options he voted already when he logs in to vote the option next time
urls.py
path('<slug>/',views.options,name='options'),
path('<slug>/vote/', views.vote, name='vote'),
models.py
class Category(models.Model):
name = models.CharField(max_length=250)
slug = AutoSlugField(populate_from='name')
details = models.TextField(blank=True)
image = models.ImageField(blank=True,upload_to='categories')
views = models.IntegerField(default=0)
created = models.DateTimeField(auto_now=True)
modified = models.DateTimeField(auto_now_add=True)
active = models.BooleanField(default=True)
def __str__(self):
return self.name
class Meta:
verbose_name_plural = "Categories"
class Option(models.Model):
name = models.CharField(max_length=250)
slug = AutoSlugField(populate_from='name')
image = models.ImageField(blank=True,upload_to='options')
details = models.TextField()
category = models.ForeignKey(Category, on_delete=CASCADE)
votes = models.IntegerField(default=0)
active = models.BooleanField(default=True)
def __str__(self):
return self.name
class Vote(models.Model):
option = models.ForeignKey(Option, on_delete=CASCADE)
voter = models.ForeignKey(User, on_delete=CASCADE)
slug = AutoSlugField(populate_from='option')
def __str__(self):
return self.voter
views.py
def options(request,slug):
category = Category.objects.get(slug=slug)
category.views += 1
category.save()
options = category.option_set.all().order_by('-votes')
if request.method == "POST":
if request.user.is_authenticated:
form = CommentForm(request.POST)
if form.is_valid():
comment = form.save(commit=False)
comment.category = category
comment.user = request.user
comment.save()
messages.success(request, 'Comment Posted.')
else:
messages.error(request, 'You have to login first to give comment')
return redirect('rank:login')
else:
form = CommentForm()
return render(request, 'rank/options.html', {'options': options,'form':form,'title': 'options','category':category})
def vote(request,slug):
if request.user.is_authenticated:
option = Option.objects.get(slug=slug)
category = option.category
if Vote.objects.filter(slug=slug,voter_id=request.user.id).exists():
messages.error(request,'You Already Voted!')
return redirect('rank:options', category.slug)
else:
option.votes += 1
option.save()
voter = Vote(voter=request.user,option=option)
voter.save()
messages.success(request,'Voted.{} peoples also agree with you.'.format(option.votes-1))
return redirect('rank:options',category.slug)
else:
messages.error(request,"You have to login first to vote.")
return redirect('rank:login')
options.html
<ol type="1">
<center>{% bootstrap_messages %}</center>
{% for option in options %}
<div class="col-lg-6 col-md-6 mb-6">
<div class="card h-100">
<div class="card-body">
<b><li>
<img src="/media/{{option.image}}" width="400" height="300">
<h4>{{option.name}}
</h4>
<h5 class="card-text">{{ option.details}}</h5>
<h5>{{ option.votes }} votes</h5>
<form action="{% url 'rank:vote' option.slug %}" method="post">
{% csrf_token %}
<input type="submit" class="btn btn-success" value="Vote" >
</form>
</li></b>
</div>
<div class="card-footer">
<small class="text-muted"></small>
</div>
</div>
</div>
{% empty %}
<div class="card w-100">
<div class="card-body">
<h4>Item not available</h4>
</div>
</div>
{% endfor %}
</ol>
The simplest way to achieve this might be to add an attribute to each option to indicate whether the currently logged in user has voted on that option before you pass the options to the template.
For example:
def options(request,slug):
category = Category.objects.get(slug=slug)
category.views += 1
category.save()
options = category.option_set.all().order_by('-votes')
# Indicate whether the user has voted or not
for option in options:
option.has_voted = option.vote_set.filter(voter=request.user).exists()
...
return render(request, 'rank/options.html', {'options': options,'form':form,'title': 'options','category':category})
And then you can check the has_voted attribute in the template when you render the button:
{% if option.has_voted %}
You already voted
{% else %}
<input type="submit" class="btn btn-success" value="Vote" >
{% endif %}

Categories