django terminate adding any input to the database from the form - python

In an auction web. I'm trying to terminate adding any input (bids, comments and add to watchlist) by any user to the database if the owner of the product press on 'close ' button so I tried to implement this pseudo code:
in views.py
function listing:
t = 1
if t == 1:
if owner clicks on the close button:
...
t = 2
if the user adds a comment:
...
if the user adds a bid:
...
if user clicks on add to watchlist button:
...
else:
return message ('Auction has ended')
I have implemented this code and the listing page accepted entries and inputs after the owner of the listing clicked on the 'close' button. I also tried to change the value of t to a boolean value ( t = True, if t == True, if user clicked: return t = False) but it didn't work. so what is the problem.
def entry(request, name):
enter = listing.objects.get(title = name)
f= bids.objects.filter(product_id = enter)
x = 0
z = ""
last = None
ended = None
like = "k"
t = 1
if t == 1:
if request.method == 'POST' and request.POST.get("bid"):
biddd = int(request.POST['bid'])
user = request.user
if biddd > x:
bids.objects.create(bid= biddd , product_id= listing.objects.get(title = name).id, user = user)
for object in f:
if object.bid > x:
if object.bid > x:
x = object.bid
if request.method == 'POST' and request.POST.get('close_bid'):
final = listing.objects.get(title = name)
last = bids.objects.get(bid = x, product = final).user
t = 2
elif request.method == 'POST' and request.POST.get("bid"):
bidd = int(request.POST['bid'])
if bidd >= x:
messages.info(request, 'bid accepted')
z = "#0a720e"
else:
messages.info(request, 'bid already present')
z = "#f44336"
elif request.method == 'POST' and request.POST.get("watchlist"):
if request.user.is_authenticated:
productt = listing.objects.get(title = name)
user = request.user
exist = watchlist.objects.filter(product = productt, user = user)
if exist.exists():
messages.info(request, 'Already added to your watchlist')
else:
watchlist.objects.create(product = productt, user = user)
else:
return render(request, "auctions/login.html")
elif request.method == 'POST' and request.POST.get("comments"):
if request.user.is_authenticated:
comment = request.POST['comments']
product = listing.objects.get(title = name)
user = request.user
comments.objects.create(comment = comment, user = user, product = product)
else:
return render(request, "auctions/login.html")
commentproduct = listing.objects.get(title = name)
commentss= comments.objects.filter( product = commentproduct)
else:
messages.info(request, 'Auction has ended')
return render(request, "auctions/entry.html" , {"enter":enter, "bid": f, "x": x, "z":z, "comments":commentss, "winner": last, "ended": ended, "l": l})
in entry.html:
{% extends "auctions/layout.html" %}
{% load static %}
{% block body %}
<h1>Listing: {{enter}}</h1>
<img src="{{enter.image}}">
<p>{{enter.description}}</p>
<h3>Current Bid: {{x}}</h3>
<form action = "#" method="POST">
{% csrf_token %}
<label>Add bid:</label>
<input type="number" name="bid">
<input type="submit">
</form>
{% for message in messages %}
<div class="alert" style="background-color:{{z}}">
<span class="closebtn" onclick="this.parentElement.style.display='none';">×</span>
{{message}}
</div>
{% endfor %}
<form method='POST' action='#'>
{% csrf_token %}
<button type="submit" name="watchlist" value="Add to watchlist"> Add to watchlist</button>
</form>
{% for message in messages %}
<h5>{{message}}</h5>
{% endfor %}
<h2>Details:</h2>
<p><strong>Owner:</strong> {{enter.author}}</p>
<p><strong>Category:</strong> {{enter.category}}</p>
<br>
<h2>Add a comment:</h2>
<form method="POST" action="#">
{% csrf_token %}
<textarea name="comments" placeholder="Add a comment" style="width:600px"></textarea>
<input type="submit" value="Add comment">
</form>
{% if user.is_authenticated and user == enter.author %}
<form method='POST' action='#'>
{% csrf_token %}
<button type="submit" name="close_bid" value="Close bid"> Close Bid</button>
</form>
{% endif %}
<h2>Comments:</h2>
{% for comment in comments %}
<h3>{{comment.user}}:</h3>
<p>{{comment.comment}}</p>
{% endfor %}
{% if user.is_authenticated and user == winner %}
<div class="alert" style="background-color:green">
<span class="closebtn" onclick="this.parentElement.style.display='none';">×</span>
You won!
</div>
{% elif not user.is_authenticated %}
<p></p>
{% else %}
<div class="alert" style="background-color:red">
<span class="closebtn" onclick="this.parentElement.style.display='none';">×</span>
You lost!
</div>
{% endif %}
{% if user.is_authenticated and user == winner %}
<p>
You won!
</p>
{% elif not user.is_authenticated %}
<p>.</p>
{% else %}
<p>you lost</p>
{% endif %}
{% endblock %}

Related

Django - Answer matching query does not exist

I am working on a form builder similar to Google Forms but I came across an error when building the 'Edit response' function.
The error stated that the "Answer matching query does not exist."
This is my HTML code for the edit response page:
28 {% endif %}
29 {% for question in form.questions.all %}
30 <div class="margin-top-bottom box question-box">
31 {% if form.is_quiz %}
32 <h1 class="question-title txtClr">{{question.question}} {% if question.required %}<span class="require-star">*</span>{% endif %}</h1>
33 {% else %}
34 <h1 class="question-title txtClr" oncopy = "return false">{{question.question}} {% if question.required %}<span class="require-star">*</span>{% endif %}</h1>
35 {% endif %}
36 {% if question.question_type == "short" %}
37 <input type="text" name="{{question.id}}" class="short-answer" placeholder="Your answer" {% if question.required %} required {% endif %}
38 value="{{response|get_response:question.pk}}">
39 {% elif question.question_type == "paragraph" %}
40 <textarea name="{{question.id}}" placeholder="Your answer" class="long-answer textarea-adjust"
41 {% if question.required %} required {% endif %}>{{response|get_response:question.pk}}</textarea>
42 {% elif question.question_type == "multiple choice" %}
43 {% for choice in question.choices.all %}
44 <div class="multiple-choice">
45 {% if response|get_response:question.pk|to_int == choice.pk|to_int %}
46 <input type="radio" name="{{question.id}}" id="{{choice.id}}" {% if question.required %} required {% endif %} value="{{choice.id}}" checked>
47 {% else %}
48 <input type="radio" name="{{question.id}}" id="{{choice.id}}" {% if question.required %} required {% endif %} value="{{choice.id}}">
The error seems to be coming from line 38, and this string "{{response|get_response:question.pk}}" was in red.
views.py:
def edit_response(request, code, response_code):
formInfo = Form.objects.filter(code = code)
#Checking if form exists
if formInfo.count() == 0:
return HttpResponseRedirect(reverse('404'))
else: formInfo = formInfo[0]
response = Responses.objects.filter(response_code = response_code, response_to = formInfo)
if response.count() == 0:
return HttpResponseRedirect(reverse('404'))
else: response = response[0]
if formInfo.authenticated_responder:
if not request.user.is_authenticated:
return HttpResponseRedirect(reverse("login"))
if response.responder != request.user:
return HttpResponseRedirect(reverse('403'))
if request.method == "POST":
if formInfo.authenticated_responder and not response.responder:
response.responder = request.user
response.save()
if formInfo.collect_email:
response.responder_email = request.POST["email-address"]
response.save()
#Deleting all existing answers
for i in response.response.all():
i.delete()
for i in request.POST:
#Excluding csrf token and email address
if i == "csrfmiddlewaretoken" or i == "email-address":
continue
question = formInfo.questions.get(id = i)
for j in request.POST.getlist(i):
answer = Answer(answer=j, answer_to = question)
answer.save()
response.response.add(answer)
response.save()
if formInfo.is_quiz:
return HttpResponseRedirect(reverse("response", args = [formInfo.code, response.response_code]))
else:
return render(request, "index/form_response.html", {
"form": formInfo,
"code": response.response_code
})
return render(request, "index/edit_response.html", {
"form": formInfo,
"response": response
})
urls.py
path('form/<str:code>/response/<str:response_code>', views.response, name="response"),
path('form/<str:code>/response/<str:response_code>/edit', views.edit_response, name="edit_response"),
Does anyone have a solution to this? Thanks

How to delete an item that is connected to a foreignkey django?

I have a problem adding a delete functionality to my simple django project which is a todoapp. The problem is when i press the delete button it redirect me to the same page but the item is not deleted. Can someone explain to me what is happening on my code?
This is my code solution but still does not work.
This is my views.py
def index(request, id):
ls = ToDoList.objects.get(id=id)
p = request.POST
if request.method == "POST":
if p.get("save"):
for item in ls.item_set.all():
item_id = str(item.id)
if "clicked" == p.get("c" + item_id):
item.complete = True
else:
item.complete = False
if p.get("text" + item_id) in p:
item.text = p.get("text" + item_id)
if p.get("d" + item_id) == "delete": # Solution
item.delete()
return HttpResponseRedirect("/%i" % ls.id)
item.save()
elif p.get("add"):
new_item = p.get("new")
if new_item:
ls.item_set.create(text=new_item)
else:
return HttpResponse("<strong>Invalid Input</strong>")
return render(request, "todoapp/index.html", {"ls": ls})
models.py
from django.db import models
class ToDoList(models.Model):
date = models.DateTimeField(auto_now_add=True)
name = models.CharField(max_length=200)
def __str__(self):
return self.name
class Item(models.Model):
toDoList = models.ForeignKey(ToDoList, on_delete=models.CASCADE)
text = models.CharField(max_length=500)
complete = models.BooleanField(default=False)
def __str__(self):
return self.text
index.html
{% extends 'todoapp/base.html' %}
{% block title %}View List{% endblock %}
{% block content %}
<h2>{{ls.name}}</h2>
<form method="post", action="#">
{% csrf_token %}
{% for item in ls.item_set.all%}
<div class="input-group mb-3">
<div class="input-group-prepend">
<div class="input-group-text">
<input class="btn btn-danger btn-sm" type="submit" name="d{{item.id}}" value="delete"> <!-- Solution -->
<input type="checkbox" name="c{{item.id}}" value="clicked" aria-label="Checkbox for following text input" {% if item.complete %} checked {% endif %}>
</div>
</div>
<input type="text" name="text{{item.id}}" value="{{item.text}}" class="form-control" aria-label="Text input with checkbox">
</div>
{% endfor %}
<div class="input-group mb-3">
<div class="input-group-prepend">
<button name="add", value="add", type="submit", class="btn btn-success">Add New</button>
</div>
<input type="text" name="new" value="" class="form-control">
</div>
<br>
<button name="save", value="save", type="submit", class="btn btn-success">Save</button>
</form>
{% endblock %}
I think it should work if you include the delete logic inside another 'if' clause.
if p.get("delete"):
for item in ls.item_set.all():
item_id = str(item.id)
if p.get("d" + item_id) == "delete": # Solution
item.delete()
return HttpResponseRedirect("/%i" % ls.id)
However, I'm not sure what you are trying to achieve as the end result. Here, only one item would get deleted (the item for which 'delete' button was clicked).

How can I avoid repetition of code within a function-based view in Django?

I have been researching how can I avoid using snippet of code over and over. The answer probably will involve using (generic) Class-based functions. However, I am a beginner in Django and this seems confusing. Here is my view in views.py:
#login_required(login_url='/login')
def view_list(request, listing_id):
bid = Bid.objects.all().filter(listing=listing_id).order_by('-id')
b_u = bid[0].user
listing = Listing.objects.get(pk=listing_id)
if request.method == "GET":
return render(request, "auctions/view_list.html", {
"form": BidForm(),
"total_bids": bid.count(),
"bid": None if bid == 0 else bid[0].bid,
"listing": listing,
"bid_user": "Your bid is the current bid." if request.user == b_u else None
})
else:
form = BidForm(request.POST)
if form.is_valid():
value = form.cleaned_data
if value['bid'] <= bid[0].bid:
error_check = True
return render(request, "auctions/view_list.html", {
"error_check": error_check,
"alert": f"Your bid is lower than the current bid $({bid[0].bid})! Try placing a higher one.",
"form": BidForm(),
"total_bids": bid.count(),
"bid": None if bid == 0 else bid[0].bid,
"listing": listing,
"bid_user": "Your bid is the current bid." if request.user == b_u else None
})
else:
error_check = False
new_bid = form.save(commit=False)
new_bid.user_id = request.user.id
new_bid.listing_id = listing.id
new_bid.save()
return render(request, "auctions/view_list.html", {
"error_check": error_check,
"alert": "Your bid was successfully placed!",
"form": BidForm(),
"total_bids": bid.count(),
"bid": None if bid == 0 else bid[0].bid,
"listing": listing,
"bid_user": "Your bid is the current bid." if request.user == b_u else None
})
And here is my template code:
{% extends "auctions/layout.html" %}
{% load humanize %}
{% load crispy_forms_tags %}
{% block body %}
{% if error_check == True %}
<div class="alert alert-warning" role="alert">
{{ alert }}
</div>
{% elif error_check == False %}
<div class="alert alert-success" role="alert">
{{ alert }}
</div>
{% endif %}
<div>
<h3>Listing: {{ listing.title }}</h3>
<img src="{{ listing.image }}" alt="Listings' Images">
<p>{{ listing.description }}</p>
{% if not bid %}
<strong>${{ listing.price|stringformat:"1.2f" }}</strong>
{% else %}
<strong>${{ bid|stringformat:"1.2f" }}</strong>
{% endif %}
<p> {{ total_bids }} bid(s) so far. {% if bid_user %} {{ bid_user }} {% endif %}</p>
<form method="POST" name="bidding" action="{% url 'view_list' listing.id %}">
{% csrf_token %}
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">$</span>
</div>
<div style="margin: 0; padding: 0 2px; height: 6px;">
{% crispy form %}
</div>
<div class="input-group-append" >
<span class="input-group-text">.00</span>
</div>
<input type="submit" class="btn btn-primary" value="Place Bid">
</div>
</form>
<h4>Details</h4>
<li>Listed by: {{ listing.user }} </li>
<li>Category: {{ listing.category }} </li>
<li>Listing created at: {{ listing.created_at }} </li>
</div>
{% endblock %}
So how can I avoid all this repetition and make the code more succinct. Also, this way when the user places a successful bid, the rendered template does not contain the new information from the form.
The pattern is very simple
def some_view(request):
form = SomeForm(request.POST or None)
if request.method == 'POST' and form.is_valid():
# Form processing
return render(request, "auctions/view_list.html", {
"form": form
})

Restrict each user to only vote once (Polls, django, python)

I found an similar question here, but unlike there and unlike in django official tutorial , I don't have a separate Choice class. How can I restrict every user to vote just one? What should I change in my code?
my models.py:
from django.contrib.auth.models import User
class Law(models.Model):
#some code here
yes_votes = models.IntegerField(default=0)
no_votes = models.IntegerField(default=0)
class Voter(models.Model):
user = models.ForeignKey(User)
law = models.ForeignKey(Law)
my views.py:
class LawDetailView(generic.DetailView):
model = Law
template_name = 'law_detail.html'
def get_queryset(self):
"""
Excludes any petitions that aren't published yet.
"""
return Law.objects.filter(pub_date__lte=timezone.now())
class LawResultsView(generic.DetailView):
model = Law
template_name = 'law_results.html'
def law_yes_vote(request, law_id):
if Voter.objects.filter(law_id=law_id, user_id=request.user.id).exists():
return render(request, 'law_detail.html', {
'law': p,
'error_message': "Sorry, but you have already voted."
})
else:
p = get_object_or_404(Law, pk=law_id)
p.yes_votes += 1
p.save()
return HttpResponseRedirect(reverse('laws:law_results', args=(p.id,)))
def law_no_vote(request, law_id):
if Voter.objects.filter(law_id=law_id, user_id=request.user.id).exists():
return render(request, 'law_detail.html', {
'law': p,
'error_message': "Sorry, but you have already voted."
})
else:
p = get_object_or_404(Law, pk=law_id)
p.no_votes += 1
p.save()
return HttpResponseRedirect(reverse('laws:law_results', args=(p.id,)))
my law_detail.html:
{% if request.user.is_authenticated %}
{% if error_message %}
<h1 >{{ error_message }}</h1>
{% else %}
<div class="row" id="row-voting">
<form action="{% url 'laws:law_yes_vote' law.id %}" method="post">
{% csrf_token %}
<button class="btn btn-success" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}" >
<label >YES</label>
</form>
<form action="{% url 'laws:law_no_vote' law.id %}" method="post">
{% csrf_token %}
<button class="btn btn-danger" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}" >
<label >NO</label>
</form>
</div>
{% endif %}
{% else %}
<h1>Please, register</h1>
{% endif %}
It looks like you have forgotten to create the voter instance after the user has voted.
def law_yes_vote(request, law_id):
if Voter.objects.filter(law_id=law_id, user_id=request.user.id).exists():
return render(request, 'law_detail.html', {
'law': p,
'error_message': "Sorry, but you have already voted."
})
else:
p = get_object_or_404(Law, pk=law_id)
p.yes_votes += 1
p.save()
Voter.objects.create(law_id=law_id, user_id=request.user.id)
return HttpResponseRedirect(reverse('laws:law_results', args=(p.id,)))
You'll need to update law_no_vote in the same way.

Error checkin Python-Flask

Here is my route function :
#app.route('/home/shelter/<int:shelter_id>/', methods=['GET','POST'])
def showShelterDetails(shelter_id):
shelter = session.query(Shelter).filter_by(id = shelter_id).one()
if request.method == 'POST':
if request.form['shelterName']:
shelter.name = request.form['shelterName']
session.add(shelter)
session.commit()
flash("Shelter("+shelter.name+") edited successfully!")
return render_template('shelterdetails.html', shelter_id=shelter_id, shelter=shelter)
else:
flash(u'Error Occured!','error')
return render_template('shelterdetails.html', shelter_id=shelter_id, shelter=shelter)
if request.form['shelterAddress']:
shelter.name = request.form['shelterAddress']
session.add(shelter)
session.commit()
flash("Shelter("+shelter.name+") address edited successfully!")
return render_template('shelterdetails.html', shelter_id=shelter_id, shelter=shelter)
else:
flash(u'Error Occured!','error')
return render_template('shelterdetails.html', shelter_id=shelter_id, shelter=shelter)
else:
return render_template('shelterdetails.html', shelter_id = shelter_id, shelter = shelter)
Here is my HTML template :
{% extends "master.html" %}
{% block title %}Home{% endblock %}
{% block body %}
{% with messages = get_flashed_messages(category_filter=["message"]) %}
{% if messages %}
<div class="alert alert-success">
{% for message in messages %}
<strong>{{message}}!</strong>
{% endfor %}
</div>
{% endif %}
{% endwith %}
{% with errors = get_flashed_messages(category_filter=["error"]) %}
{% if errors %}
<div class="alert alert-danger">
{% for message in errors %}
<strong>{{message}}!</strong>
{% endfor %}
</div>
{% endif %}
{% endwith %}
<form action="{{ url_for('showShelterDetails',shelter_id=shelter_id )}}" method = 'post'>
<fieldset class="form-group">
<label for="shelterName">Name :</label>
<input type="text" class="form-control" style="width:500px" name="shelterName" value='{{ shelter.name }}' >
</fieldset>
<fieldset class="form-group">
<label for="shelterName">Address :</label>
<input type="text" class="form-control" style="width:500px" name="shelterAddress" value='{{ shelter.address }}'>
</fieldset>
My problem is : The POST method doesn't check whether the shelterAddress field is empty or blank or not. Also while returning the success or failure messages. Only the top 1 message gets printed.
Why do the other messages not get printed ? Also why doesn't it check for empty fieds ?
EDIT 1:
Changed my view function to :
#app.route('/home/shelter/<int:shelter_id>/', methods=['GET','POST'])
def showShelterDetails(shelter_id):
shelter = session.query(Shelter).filter_by(id = shelter_id).one()
if request.method == 'POST':
if request.form['shelterName']!="":
shelter.name = request.form['shelterName']
session.add(shelter)
session.commit()
flash("Shelter("+shelter.name+") edited successfully!")
if request.form['shelterAddress']!= "":
shelter.name = request.form['shelterAddress']
session.add(shelter)
session.commit()
flash("Shelter("+shelter.name+") address edited successfully!")
else:
return render_template('shelterdetails.html', shelter_id = shelter_id, shelter = shelter)
ValueError: View function did not return a response
That's because you're returning early whether request.form['shelterName'] is truthy or not. You probably want one return statement at the very end of your view function instead.

Categories