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

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 %}

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>

forms in Django does not register the data in the database

I'm stuck I try a lot of things to make it work, but always the same problem the form dose note save the data at all
and the any error that I get is the message error (what I writ in the message)
all i get is a change in the url like this
http://127.0.0.1:8000/appointement/create_appointement_2?patient=patient+12&initial-patient=patient+12&doctor=2&date=2021-04-02&start_time=16%3A30
is there anything that can show me the error or if anyone have this problem be for a few hits will be awesome?
this is my models .py
class Appointment(models.Model):
user_ho_add = models.ForeignKey(User, on_delete=models.CASCADE, related_name='user_ho_add_appointment')
patient = models.CharField(null=True,max_length = 200, default=defaultTitle)
doctor = models.ForeignKey(User, on_delete=models.CASCADE, related_name='doctor_app')
date = models.DateField(null=False, blank=False, default=timezone.now)
start_time = models.TimeField(null=True, blank=True, default=timezone.now)
end_time = models.TimeField(null=True, blank=True, default=timezone.now)
and this is my forms.py
class AppointmentForm_2(forms.ModelForm):
doctor = forms.ModelChoiceField(queryset=User.objects.filter(type_of_user=TypeOfUser.DOCTOR))
# patient = forms.ModelChoiceField(queryset=User.objects.filter(type_of_user=TypeOfUser.PATIENT))
date = forms.DateField(widget=forms.DateInput(attrs={'type': 'date'}), input_formats=settings.DATE_INPUT_FORMATS)
start_time = forms.DateField(widget=forms.DateInput(attrs={'type': 'time'}), input_formats=settings.TIME_INPUT_FORMATS)
class Meta:
model = Appointment
fields = ('patient', 'doctor', 'date', 'start_time')
and this is the views.py
#login_required
def create_appointement_2(request):
user = get_user_model()
patients = User.objects.filter(type_of_user=TypeOfUser.PATIENT)
form_appointment_2 = AppointmentForm_2(request.POST or None)
if request.user.is_doctor() or request.user.is_reception():
if request.method=='POST':
form_appointment_2 = AppointmentForm_2(request.POST or None)
user = get_user_model()
if form_appointment_2.is_valid():
form_appointment_2.save(commit=False)
form_appointment_2.user_ho_add = request.user
# form_appointment.end_time = form_appointment.start_time + timedelta(minutes=30)
start_time = form_appointment_2.start_time
future_time = dt.datetime(1970, 1, 1, start_time.hour, start_time.minute, start_time.second, start_time.microsecond) + timedelta(minutes=30)
form_appointment_2.end_time = dt.time(future_time.hour, future_time.minute, future_time.second, future_time.microsecond)
form_appointment_2.save()
messages.success(request, 'appointment added')
else:
messages.error(request, 'Error')
else:
return render(request, 'appointement/add_appointement2.html', {'user_form':form_appointment_2,'patients':patients })
return render(request, 'appointement/add_appointement2.html', {'user_form':form_appointment_2,'patients':patients })
and this the html file
<body>
{% if form.errors %}
<div class="alert alert-danger alert-dismissible col-12 mx-1" role="alert">
<div id="form_errors">
{% for key, value in form.errors.items %}
<span class="fieldWrapper">
{{ key }}:{{ value }}
</span> {% endfor %}
</div>
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
{% endif %}
<div class="container">
<form>
{{ user_form.media }} {{ user_form }} {% csrf_token %}
<button type="submit" value="create_appointment">
ok
</button>
</form>
</div>
</body>
I try to add the error tag, but it shows nothing, all i get is a change in the url like this
http://127.0.0.1:8000/appointement/create_appointement_2?patient=patient+12&initial-patient=patient+12&doctor=2&date=2021-04-02&start_time=16%3A30
if you are getting the data in the url that means you need to add method="POST" to your form tag in the html file

Show data after dropdown selection

I am struggling with my code. I want to show data from a specific user on screen. When the second dropdown is selected with the user from a specific group, I want his records to be shown on screen. But what ever I try, the data stays the same from one user. In a later stadium I want to make an Else and say if there is no data, that there is no data of the person. Should I do something with a jquery, or is there an easier way to solve this?
The first dropdown is the group, the second dropdown the user.
models.py
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class DisplayGroups(models.Model):
group_name = models.CharField(max_length=200)
def __str__(self):
return self.group_name
class DisplayUsername(models.Model):
username = models.CharField(max_length=100)
def __str__(self):
return self.username
class CijferLijst(models.Model):
name = models.CharField(max_length=200, default='')
vak1 = models.CharField(max_length=200, default='')
cijfer1 = models.DecimalField(max_digits=3, decimal_places=1, default='1.0')
vak2 = models.CharField(max_length=200, default='')
cijfer2 = models.DecimalField(max_digits=3, decimal_places=1, default='1.0')
username = models.ForeignKey(User, on_delete=models.CASCADE, default='')
def __str__(self):
return '%s %s %s %s %s %s'%(self.name, self.vak1, self.cijfer1, self.vak2, self.cijfer2, self.username)
bekijk.html
{% extends 'home/base.html' %}
{% block title %}Cijfers studenten{% endblock %}
{% block javascript %}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
$(document).ready(function()
{
var $select1 = $('#groupdd1'),
$select2 = $('#userdd1'),
$options = $select2.find('option');
$select1.on('change', function()
{
$select2.html($options.filter('[value="'+this.value+'"]'));
}).trigger('change');
});
</script>
{% endblock %}
{% block content %}
{% if user.is_staff %}
<h1>Studentresultaten</h1>
<select id="groupdd1">
<option disabled="true" selected>Kies een groep</option>
{% for result in DisplayGroups %}
<option>{{result}}</option>
{% endfor %}
</select>
<select id="userdd1">
<option disabled="true" selected>Kies een gebruiker</option>
{% for result in DisplayUsername %}
<option value="{{result.username}}">{{result}}</option>
{% endfor %}
</select>
{% endif %}
<br/>
{% for antwoord in CijferLijst %}
<h2>{{antwoord.name}}</h2>
<div class="container px-4">
<div class="row justify content-start gx-5">
<div class="col-5 border bg-light"><strong>Vaknaam</strong></div>
<div class="col-5 border bg-light"><strong>Cijfer</strong></div>
</div>
<div class="row gx-5 justify-content-start">
<div class="col-5 border bg-light">{{antwoord.vak1}}</div>
<div class="col-5 border bg-light">{{antwoord.cijfer1}}</div>
</div>
<div class="row gx-5 justify-content-start">
<div class="col-5 border bg-light">{{antwoord.vak2}}</div>
<div class="col-5 border bg-light">{{antwoord.cijfer2}}</div>
<div class="col-5 border bg-light">{{antwoord.username}}</div>
</div>
</div>
{% endfor %}
{% endblock %}
views.py
from django.shortcuts import render, redirect
from .models import DisplayGroups, DisplayUsername, CijferLijst
from .forms import Grades
from django.contrib.auth.models import User, Group
# Create your views here.
def index(request):
response = redirect('/login')
return response
def home(response):
return render(response, "home/home.html")
def bekijk(request):
DisplayGroup = Group.objects.all()
print(DisplayGroup)
DisplayNames = User.objects.all()
print(DisplayNames)
Cijfer = CijferLijst.objects.all()
print(Cijfer)
return render(request, "home/bekijk.html",
{"DisplayGroups": DisplayGroup, "DisplayUsername": DisplayNames, "CijferLijst": Cijfer})
def cijfers(request):
if request.method == "POST":
form = Grades(request.POST)
if form.is_valid():
form.save()
print(form)
return redirect('gelukt')
else:
form = Grades()
return render(request, "home/cijfers.html", {"form":form})
def done(response):
return render(response, "home/gelukt.html")
forms.py
from django import forms
from .models import CijferLijst
from django.contrib.auth.models import User
class Grades(forms.ModelForm):
name = forms.CharField(max_length=200)
vak1 = forms.CharField(max_length=200)
cijfer1 = forms.DecimalField(max_digits=3, decimal_places=1)
vak2 = forms.CharField(max_length=200)
cijfer2 = forms.DecimalField(max_digits=3, decimal_places=1)
username = forms.ModelChoiceField(queryset=User.objects.all())
check = forms.BooleanField()
class Meta:
model = CijferLijst
fields = ['name', 'vak1', 'cijfer1', 'vak2', 'cijfer2', 'username']
Thanks in advance.

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

Most effective way to create Attending Event option button [Django/Python]?

Trying to implement an "Attending" button. It's simple (or so I thought). A user with a profile clicks "Attending", and a checkmark appears. Can't quite get this to work on the Django/Python side of things. ie: Put that user who clicked 'Attending' into the attendee(list) within the Event.
Template:
{% if is_attending %}
<button class="btn" disabled="disabled">
<i class="icon-ok-sign"></i> Attending
</button>
{% else %}
<form class="left" method="POST" action="/profile/event/{{ event.id }}/">
{% csrf_token %}
<input type="hidden" name="profile_id" value="user" />
<button class="btn">
Attending
</button>
</form>
{% endif %}
Models:
class Event(models.Model):
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
owner = models.ForeignKey(User, null=True, blank=True, on_delete=models.SET_NULL)
name = models.CharField(max_length=200)
location = models.CharField(max_length=200)
start_date = models.DateTimeField(auto_now=False, auto_now_add=False)
end_date = models.DateTimeField(auto_now=False, auto_now_add=False)
about = models.TextField(null=True, blank=True)
attendees = models.ManyToManyField(Profile, null=True, blank=True)
View:
#login_required
def attending_event(request, event_id):
event = get_object_or_404(Event, id=event_id)
if request.method == 'POST':
try:
id = request.POST.get('profile_id')
attendee = Profile.objects.get(id=id)
relationship = Event.objects.create(attendees__user=attendee)
is_attending = True
except:
pass
return HttpResponseRedirect('/profile/event/' + event_id + '/')
else:
if not Event.objects.filter(attendees__user=request.user).exists():
is_attending = False
data = {
'is_attending': is_attending
}
return render_to_response('profiles/event.html', data, context_instance=RequestContext(request))
Maybe there's something I'm missing and can't see what it is I'm doing wrong. But if anyone could offer some insight/advice about how to go about completing this; I'd really appreciate it.
Just giving you hint, change it according to your needs
Template:
{% if is_attending %}
<button class="btn"> # this code will executes when is_attending is True
<i class="icon-ok-sign"></i> Attending
</button>
{% else %}
<form class="left" method="POST" action="/profile/event/{{ event.id }}/"> # Always user reverse urls instead of Hard coded
{% csrf_token %}
<input type="hidden" name="profile_id" value="{{profile.id}}" />
<button class="btn">
Attending
</button>
</form>
{% endif %}
View:
#login_required
def event_profile(request, event_id)
event = get_object_or_404(Event, id=event_id)
if request.method == 'POST':
try:
id = request.POST.get('profile_id')
attendee = Profile.objects.get(id=id)
relationship = Event.objects.create(attendees__user=attendee, .... ) # set other variable you want
is_attending = True
else:
# check in your event either your profile user is already attending or not? and set is_attending variable according to it
data = {
'is_attending': is_attending,
....
}
return render_to_response('my_template.html',
data,
context_instance=RequestContext(request))

Categories