Flask Form Only Passing First Item - python

I am building a cart using Flask for learning purposes. I chose to use SQLite with peewee(ORM) and WTForms. I have it set to display the items from the db with a description and image. I have a form that asks for the quantity then it should add the item and its quantity to the side bar.
The Issue
When You enter a quantity and hit 'add' all the quantity fields will fill with that number and it will post the name of the first item from the database to the sidebar with that quantity.
app.py
#app.route('/cart', methods=['GET', 'POST'])
#login_required
def cart():
form = forms.PartsSelectForm()
if request.method == 'POST':
l_name = Parts.get(Parts.id).part_name
models.List.create(l_part_name=l_name,
l_part_qty=form.quantity.data)
parts = Parts.select()
list = List.select()
return render_template('cart.html', parts=parts, list=list, form=form)
forms.py
class PartsSelectForm(Form):
quantity = IntegerField()
cart.html
<table class="table">
<thead>
<tr>
<th>Name</th>
<th>Description</th>
<th>Image</th>
<th>Quantity</th>
<th>Action</th>
</tr>
</thead>
{% for part in parts %}
<tr>
<td>{{ part.part_name }}</td>
<td>{{ part.part_desc }}</td>
<td style="width: 200px; height:200px;"><img src="/static/img/{{ part.part_img }}" style="max-height:100%; max-width:100%"></td>
<form method="POST" action="">
<td>{{ form.quantity }}</td>
<td><button type="submit" id="submit" class="btn btn-success">Add</button></td>
</form>
</tr>
{% endfor %}
</table>

You loop over your parts, but you always use form.quantity, which will be the same on every iteration idependently from which "part" you're currently looping over.

Related

Django: select all data from a row in a html table and use them in a view

I am new to both django and web development.
The task is to run a script when pressin a button using the data contained in the specific row of an html table.
So if i clik on the second button "Run script" it uses all the data in that row (8888, 2020/06/21 06:00) in a separate script to performe some task.
Currently my html file looks like this:
There are 2 sections one for uplading the information that goes in the table one the table which displays them
<h1>Approach Path KML Generator</h1>
<h2>Generate the KML file here:</h2> <form method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<button onclick="location.href='{% url 'approach_path_receptorsKML:Proejct Creator' %}'">Upload</button> </form>
<h2>Projects Available:</h2>
<table class="table">
<thead>
<tr>
<th>Project ID</th>
<th>Date KML</th>
<th>Time KML</th>
<th>Date-Time Uploaded</th>
<th>Run The Conversion</th>
<th>KML File</th>
</tr>
</thead>
<tbody>
{% for project in latest_project_list %}
<tr>
<td>{{ project.project_ID }}</td>
<td>{{ project.date_kml }}</td>
<td>{{ project.time_kml }}</td>
<td>{{ project.upload_time }}</td>
<td>
<button method="post" value="collect data" name="{{ project.project_ID }}|{{ project.date_kml }}|{{ project.time_kml }}|{{ project.upload_time }}">Run script</button>
</td>
<td>
Download KML File
</td>
</tr>
{% endfor %}
</tbody> </table>
And this is the view I have created:
def ProjectCreator(request):
form = DocumentForm()
if request.method == 'POST':
form = DocumentForm(request.POST, request.FILES)
if form.is_valid:
form.save()
elif 'collect data' in request.POST.values():
values = [key for key in request.POST.keys()]
print(values)
else:form = DocumentForm()
I have tried to use this guide (How do I pass table data from a template over to Django on a button/submit click?) however, I have been insuccesfull.
If anyone can spot the mistake I have made and give me some explanation I would be grateful.
Thanks
It doesn't work because you have incorrect HTML layout. Button itself doesn't do anything - in order to send POST request, it should be in <form> tag. Try following:
{% for project in latest_project_list %}
<tr>
<td>{{ project.project_ID }}</td>
<td>{{ project.date_kml }}</td>
<td>{{ project.time_kml }}</td>
<td>{{ project.upload_time }}</td>
<td>
<form method="post">
{% csrf_token %}
<button value="collect data"
name="{{ project.project_ID }}|{{ project.date_kml }}|{{ project.time_kml }}|{{ project.upload_time }}">
Run script
</button>
</form>
</td>
<td>
Download KML File
</td>
</tr>
{% endfor %}
This will work, but I doubt this is great way of achieving this. You can just send project.pk with POST request and fetch project in view. This way you can be sure user will not send incorrect/malicious data with request. It is especially important since your code will run script based on data.

I am having errors with CS50 Finance problem in registration process

The error is ":( registering user succeeds" and ":( registration rejects duplicate username"
The detailed error log mentions that there is no table such as 'stock found'
Other registration processes have green ticks.
Can someone please help out with this code?
Here is my registration code in application.py
#app.route("/register", methods=["GET", "POST"])
def register():
"""Register user"""
# Forget any user_id
session.clear()
# User reached route via POST (as by submitting a form via POST)
if request.method == "POST":
# Ensure username was submitted
if not request.form.get("username"):
return apology("Oh dear, give us the username!")
# Ensure password was submitted
elif not request.form.get("password"):
return apology("You have to give us password!")
elif not request.form.get("confirmation"):
return apology("You have to confirm your password!")
# Ensure confirm password is correct
elif request.form.get("password") != request.form.get("confirmation"):
return apology("Oops, your passwords don't match up!")
# Insert user and hash of the password into the table
newuser = db.execute("INSERT INTO users (username, hash) VALUES (:username, :hash)",
username=request.form.get("username"),
hash=generate_password_hash(request.form.get("password")))
if not newuser:
return apology("Someone else swiped right on this Username, try a new one!")
# Query database for username
rows = db.execute("SELECT * FROM users WHERE username = :username",
username=request.form.get("username"))
# Remember which user has logged in
session["user_id"] = rows[0]["id"]
# Redirect user to home page
return redirect(url_for("index"))
# User reached route via GET (as by clicking a link or via redirect)
else:
return render_template("register.html")
I have also given below the index code below - for the error with 'stock' table
#app.route("/")
#login_required
def index():
"""Show portfolio of stocks"""
# Query infos from database
rows = db.execute("SELECT * FROM stocks WHERE user_id = :user",
user=session["user_id"])
cash = db.execute("SELECT cash FROM users WHERE id = :user",
user=session["user_id"])[0]['cash']
# pass a list of lists to the template page, template is going to iterate it to extract the data into a table
total = cash
stocks = []
for index, row in enumerate(rows):
stock_info = lookup(row['symbol'])
# create a list with all the info about the stock and append it to a list of every stock owned by the user
stocks.append(list((stock_info['symbol'], stock_info['name'], row['amount'], stock_info['price'], round(stock_info['price'] * row['amount'], 2))))
total += stocks[index][4]
return render_template("index.html", stocks=stocks, cash=round(cash, 2), total=round(total, 2))
HTML for register
{% extends "layout.html" %}
{% block title %}
Register
{% endblock %}
{% block main %}
<form action="/register" method="post">
<fieldset>
<div class="form-group">
<input autocomplete="off" autofocus class="form-control" name="username" placeholder="Username" type="text">
</div>
<div class="form-group">
<input class="form-control" name="password" placeholder="Password" type="password">
</div>
<div class="form-group">
<input class="form-control" name="confirmation" placeholder="Confirm password" type="password">
</div>
<button class="btn btn-primary" type="submit">Register</button>
</fieldset>
</form>
{% endblock %}
HTML for Index
{% extends "layout.html" %}
{% block title %}
Stocks
{% endblock %}
{% block main %}
<table class="table">
<thead class="thead-light">
<tr>
<th scope="col">Symbol</th>
<th scope="col">Name</th>
<th scope="col">Shares</th>
<th scope="col">Price</th>
<th scope="col">Total</th>
</tr>
</thead>
<tbody>
{% for stock in stocks %}
<tr>
<th scope="row">{{ stock[0] }}</th>
<td>{{ stock[1] }}</td>
<td>{{ stock[2] }}</td>
<td>{{ stock[3] }}</td>
<td>{{ stock[4] }}</td>
</tr>
{% endfor %}
<tr>
<th scope="row">Cash</th>
<td></td>
<td></td>
<td></td>
<td>{{ cash }}</td>
</tr>
<tr>
<th scope="row"></th>
<td></td>
<td></td>
<td></td>
<td>{{ total }}</td>
</tr>
</tbody>
</table>
{% endblock %}
Before Insert user and hash of the password into the table, do SELECT on the request.form.get("username"), to see if the username already exists. Then if something is returned, return an error message. I think that should solve the problem.

remove from cart using form in template not working in Django

I'm building an Ecommerce App using Django, I'm storing my cart object in Django Sessions, Add to cart, reduce quanity & increase quantity seem to work perfectly on the products page but the same logic isnt working on the cart page. Django isnt throwing any errors. Below is the snippet of code of my form located inside a table on the Cart page & the view function handling its post request:
FORM:
<div class="container">
<div class="border rounded p-4 m-4">
<p class="display-4 pl-4 ml-4">Your Cart</p>
<hr>
<table class="table">
<thead>
<tr>
<th>Sno.</th>
<th>Image</th>
<th>Product</th>
<th>Price</th>
<th>Quantity</th>
<th>Total</th>
<th> </th>
</tr>
</thead>
<tbody>
{% for product in products %}
<tr>
<td>{{forloop.counter}}</td>
<td>___</td>
<td>{{product.name}}</td>
<td>{{product.price}}</td>
<td>{{product|cart_quantity:request.session.cart}}</td>
<td>{{product|price_total:request.session.cart}}</td>
<td>
<form action="/cart/#{{product.id}}" method="POST">
{% csrf_token %}
<input hidden type="text" name="product" value="{{product.id}}">
<input hidden type="text" name="remove" value="True">
<input type="submit" value=" * " class="btn btn-block btn-light border-right">
</form>
</td>
</tr>
{% endfor %}
</tbody>
<tfoot>
<tr>
<th colspan="4"></th>
<th class="" colspan="">Total</th>
<th>{{products|total_cart_price:request.session.cart}}</th>
</tr>
</tfoot>
</table>
VIEW FUNCTION:
class Cart(View):
def get(self, request):
ids = list(request.session.get('cart').keys())
products = Product.get_products_by_id(ids)
return render(request , 'cart.html' , {'products' : products} )
def post(self, request):
product = request.POST.get('product')
remove = request.POST.get('remove')
cart = request.session.get('cart')
if remove:
cart.pop(product)
else:
pass
return redirect('cart')
Apparently django sessions object needs to be made aware anytime any changes are to be made to the object inside sessions. The fix is to add :
request.session.modified = True
I'm testing this rn and it seems to work fine, what i dont get is why on the homepage it works without adding the modified command. If anyone has any further knowledge on this issue. Do share

Checked rows are not being deleted from HTML table/ Database (Django)

I created an html table in a django template
<form action="/delete_team/" method="POST" >
{% csrf_token %}
<input type="submit" name = "delete" class="btn btn-danger float-right" value="Delete">
<table>
<thead>
<tr>
<th><input type="checkbox" class="checkAll" name="checkAll"></th>
<th>Team ID</th>
<th>Male</th>
<th>Female</th>
<th>Officer</th>
<th>Deadline</th>
</tr>
</thead>
<tbody>
{% for team in teams %}
<tr>
<td><input type="checkbox" name="checked" class="case"></td>
<td>{{ team.team_id}}</td>
<td>{{ team.male }}</td>
<td>{{ team.female }}</td>
<td>{{ team.officer }}</td>
<td>{{ team.date }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</form>
here is the code that i wrote in my views.py:
def delete_team(request):
if request.method == "POST":
pkm = request.POST.getlist("checked")
selected_objects = mtch_tbl.objects.filter(team_id__in=pkm)
selected_objects.delete()
return HttpResponseRedirect("/main/")
now when i check a row and click delete nothing happens...i only get returned to my page again with the same data. Kindly point out my mistake, i can't figure out how to write the views
Here are my urls.py
from django.urls import path
from teamplanner import views
urlpatterns = [
...
path("delete_team/",views.delete_team),
]
Is it possible for the jQuery code to be interfering?
Your views have many codes that to me aren't necessary, if you're planning on deleting a team, it's just Normal that you've FIRST registered a team. So here's what you should do..
def delete_team(request,delete_id):
delete = mtch_tbl.objects.get(id=delete_id)
#to make it more interesting, you should add a view to your models (i,'ll display the model below)
delete.view=True
delete.delete()
return HttpResponseRedirect("/main/")
Add this to your models
Class modelname (models.Model):
view=models.BooleanField(default=False)
In your URLs here's what you should do:
urlpatterns = [
path("delete_team/(?<delete_id>\d+)/$",views.delete_team),
]''''
I hope this helps
I think you're storing it in a variable. Try this:
def delete_team(request):
if request.method == "POST":
pkm = request.POST.getlist("check")
mtch_tbl.objects.filter(team_id__in=pkm).delete()
return HttpResponseRedirect("/main/")
I figured out the answer after reading this S.O solution, it's not related to checkboxes but the idea is pretty much the same. All I did was edit my checkbox input tag a little and added values to it:
<tbody>
{% for team in teams %}
<tr>
<td><input type="checkbox" name="checked" class="case" value="{{ team.team_id }}"></td>
<td>{{ team.team_id}}</td>
<td>{{ team.male }}</td>
<td>{{ team.female }}</td>
<td>{{ team.officer }}</td>
<td>{{ team.date }}</td>
</tr>
{% endfor %}
</tbody>
that's all there was to it, no need to change the views or the url path.
Still I really appreciate the help, Thank You!

Get the values for selected multiple checkbox in Django

I am building an app with django. Now i am facing a problem with checkbox. I can retrive the values from request.POST.getlist(checkbox[]). But its comming with a list. Then i am making a for loop to use the slug to get the prices but here i faced like how to store it with a separate variable for each check box. As it is in loop, for different values with different variables is not possibe? How could i do it ?
In my model I have one table with extras. It has SSL, SECURITY, BACKUP.
If the check box of SSL and SECURITY selected then by the slug I will get the price. But i want that to add to Order model which has a fields like SSL and SECURITY .
I am getting totaly confused. How should I make the model architecture. With Hosting user can buy SSL, SECURITY, BACKUP or any of them.
def checkout(request):
if request.method == "POST":
extras_slugs = request.POST.getlist("checkbox[]")
for slug in extras_slugs:
You should use request.POST.getlist here. This is example where I am storing attendance data based on checkbox.
in views:
if request.method == "POST":
id_list = request.POST.getlist('choices')
in html
<form action="{% url 'submitattendance' %}" method="post" role="form">
{% csrf_token %}
<table class="table table-hover">
<thead>
<tr>
<th>Name</th>
<th>Status</th>
<th><input type="checkbox" align="center" onClick="toggle(this)"></th>
</tr>
</thead>
<tbody>
{% for attendance in attendances %}
<tr {% if attendance.present %} style="background-color:green;"{% endif %}>
<td>{{attendance.first_name}} {{attendance.last_name}}</td>
<td>{{attendance.status}}</td>
<td><input type="checkbox" name="choices" value="{{attendance.id}}" {% if attendance.present %} checked="checked"{% endif %} class="checkbox_delete"></td>
<td><input type="hidden" name="attendances" value="{{attendance.id}}"></td>
</tr>
{% endfor %}
</tbody>
</table>
Hope this helps.

Categories