SQLAlchemy/Flask not showing records in table - python

Currently programming a small app in Flask for school.
I made a DB and the I've put some data in there, simple nothing to worry about.
I created a query to get all of the records out and show them in a html table,
all I get is <player 1> or <player 2>, but not the actual name or player ID.
In the route:
#main.route('/')
#login_required
def index():
from .models import Players
playerdetails = Players.query.all()
return render_template('index.html', name=current_user.name, playerdetails=playerdetails)
the HTML:
<tbody>
{% for players in playerdetails %}
<tr>
<td>{{ playerdetails[1] }}</td>
<td>{{ playerdetails[2] }}</td>
</tr>
{% endfor %}
</tbody>
This is what I have in the database:
This is what the website shows:
I can add more players, and the table gets bigger. and if I change it to {{ playerdetails[3] }}
it'll just show < players 4 >

Figured it out.
I had to do {{ players.name }} and {{ players.player_number }}
small mistake that can really grind your gears for hours.

Related

Flask - cant post to route [duplicate]

This question already has answers here:
Sending data from HTML form to a Python script in Flask
(2 answers)
Closed last year.
I'm creating a configurator app for heating systems. Essentially the idea is by putting in a few inputs - the app will spit out the part number for a system pack where a user can see a detailed bill of material (BOM).
One key element is the output where we need to show a few options. I.e. if someone needs a 200kW system, there could be 3-4 packs that are suitable (190kW -210kW might be more cost effective).
I want in the first instance to show on a route the pack options that are suitable- then the user selects the pack they want- which takes you to a route (/cart) which shows the BOM.
I have put in input variables min and max which searches a database cascades.db. This successfully shows me the table of options.
from cs50 import SQL
from flask import Flask, render_template, request, url_for, redirect
app = Flask(__name__)
db = SQL("sqlite:///cascades.db")
#app.route("/")
def index():
return render_template("index.html")
#app.route("/search", methods=["GET", "POST"])
def search():
output = request.form.get("output")
hydraulic = request.form.get("hydraulic")
layout = request.form.get("layout")
controls = request.form.get("controls")
min_output = int(output) - 15
max_output = int(output) + 15
cascades = db.execute("SELECT * FROM cascades WHERE hydraulic = ? AND layout = ? AND output BETWEEN ? and ?", hydraulic, layout, min_output, max_output)
return render_template("search.html", cascades=cascades)
#app.route("/cart", methods=["GET", "POST"])
def cart():
bom_id = request.form.get("bom_id")
bom = db.execute("SELECT * FROM bom WHERE bom_id = ?", bom_id)
return render_template("bom.html", bom = bom)
When running the app- the first bit works - i.e. it shows me a list of all the packs that meet the criteria- but when clicking the 'Choose' button Im getting stuck.
{% extends "layout.html" %}
{% block body %}
<h3> Boiler Cascade Pack Options:</h3>
<table class="table table-striped table-boardered">
<tr>
<th>Part Number</th>
<th>Description</th>
<th>Number of boilers</th>
<th>BOM</th>
</tr>
{% for cascades in cascades %}
<tr>
<td scope="cascades">{{ cascades["id"] }}</td>
<td>{{ cascades["description"] }}</td>
<td>{{ cascades["number_of_boilers"] }}</td>
<td>
<form action "/cart" method="post">
<input name="bom_id" type="hidden" value="{{ cascades["id"] }}">
<input class="btn btn-primary" type="submit" value="Choose">
</form>
</td>
</tr>
{% endfor %}
</table>
{% endblock %}
But when submitting the form- where they select the pack (which has the pack id number- as a hidden form) I get the following error:
File "/home/ubuntu/cascade2/application.py", line 26, in search
min_output = int(output) - 15 TypeError: int() argument must be a
string, a bytes-like object or a number, not 'NoneType'
It seems like the route is trying to use the same logic in the second search but at this point its redundant. The second search all I want is to show me information where the Pack id = BOM.
I've noticed the URL stays on the (/search) route with this and not going to the (/cart).
I've tried several things such as putting in a IF NOT output- redirect to Cart to try and bi pass this- which successfully loads the bill of material page but nothing comes up as I don't think its posted the id to the route.
I've also changed it to GET instead of POST, which results in the query string /search?bom_id=71723827132. Which shows its picking up the part number- but staying on the /search route where I see the error.
<h3> Boiler Cascade Pack Options:</33>
<table class="table table-striped table-boardered">
<tr>
<th>Part Number</th>
<th>Description</th>
<th>Number of boilers</th>
</tr>
{% for cascade in cascade %}
<tr>
<td scope="cascade">{{ cascades["id"] }}</td>
<td>{{ cascades["description"] }}</td>
<td>{{ cascades["number_of_boilers"] }}</td>
</tr>
{% endfor %}
</table>
<br>
<h4>Bill of material:</h4>
<br>
<table class="table table-striped table-boardered">
<tr>
<th>Product ID</th>
<th>Product Description</th>
<th>Quantity</th>
</tr>
{% for bom in bom %}
<tr>
<td scope="bom">{{ bom["part_number"] }}</td>
<td>{{ bom["product_description"] }}</td>
<td>{{ bom["quantity"] }}</td>
</tr>
{% endfor %}
</table>
Been stuck on this for a month. This to me is the last piece of the puzzle. Any help/suggestions would be great. I'm new to programming so I bet I've missed something obvious :)
Your <form action "/cart" method="post"> is missing an = after action. That means the action attribute is not properly defined, and the default for action always is the URL you're currently on. That's why it stays at /search.

how to perform a query with filter in the django template

hello family by the way I am a beginner in web programming with the python language and its django framework
my concern is to be able to display the information coming from the join of several tables or models in my case I have the following tables:
Country table
city ​​table
church table
but I used the mptt for country and city and everything is working fine but I want to display the list of all the countries with their respective cities as well as all the churches for each city. this is where the great difficulty lies for the month. If there is someone who can help me I will be very very happy
Have something like this in your view, where you pass in your tables:
def TestView(request):
#...
countries = CountryModel.objects.all()
cities = CitiesModel.objects.all()
churches = ChurchesModel.objects.all()
#...
And then in your template, you can format these to seem like they are part of the same table. Use for loops to go through the models in your database. For example something like this should make a table with all of the items (assuming name is a parameter of the model:
<table>
<tr>
<td>Countries: </td>
{% for country in countries %}
<td>{{ country.name}}</td>
{% endfor %}
</tr>
<tr>
<td>Cities: </td>
{% for city in cities %}
<td>{{ city.name}}</td>
{% endfor %}
</tr>
<tr>
<td>Churches: </td>
{% for church in churches %}
<td>{{ church.name}}</td>
{% endfor %}
</tr>
</table>

How do I use Flask's url_for in a template?

I am building a Flask application to manage character sheets for an RPG using an SQL database.
Currently, I have the following script that displays the list of a user's characters currently in the database.
#app.route("/<cha_name>")
#login_required
def character_sheet():
characters = db.execute(
"""SELECT
*
FROM
characters
WHERE
user_id = :user_id AND
name = :cha_name
""",
user_id=session["user_id"],
cha_name="???",
)
if not characters:
return render_template("add_char.html")
I would like to include a button that navigates to the character sheet for the specic chosen character. So the page below would detail some of the stats for the character, and then a button would take the user to a populated character sheet on another page.
This is what I have so far for displaying a specific user's characters.
{% extends "main.html" %}
{% block title %}
Characters
{% endblock %}
{% block main %}
<table border = 1>
<thead>
<td>Player</td>
<td>Name</td>
<td>Race</td>
<td>Class</td>
<td>Level</td>
<td>Status</td>
<td>View</td>
</thead>
{% for row in rows %}
<tr>
<td>{{ character["user"] }}</td>
<td>{{ character["name"] }}</td>
<td>{{ character["race"] }}</td>
<td>{{ character["cha_class"] }}</td>
<td>{{ character["level"] }}</td>
<td>{{ character["status"] }}</td>
<td><a href={{ url_for('cha_name') }}>View Sheet</a></td> <!-- HERE -->
</tr>
{% endfor %}
</table>
Add a new Character
Go back to home page
</body>
{% endblock %}
What do I use on the line with <!-- HERE --> to make a link to the character sheet URL?
Whew, there's a lot to unpack here!
Your example is/was invalid, e.g. cha_name= on the end of the db.execute() call, and there are no calls to render_template if a character is found, so it'll never produce a response even with a valid request.
Next, you've told Flask to pass a cha_name parameter to your character_sheet function, but haven't defined a parameter on the function itself.
Finally, in your template you're passing cha_name to the url_for function, which (so far as we can see from the sample code) isn't a route that you've defined, so can't work.
You need to include more information for us to help, such as telling us what error you're seeing. Right now, I imagine the Flask service won't even start due to the syntax error. Once that's fixed, I'd expect to see something like the following:
werkzeug.routing.BuildError: Could not build url for endpoint 'cha_name'. Did you mean 'character_sheet' instead?
I'd suggest you head back to the documentation on URL building and also look at the docs for the route decorator. You'll see on the latter that "Flask itself assumes the name of the view function as endpoint". That means that in order to get Flask to generate a URL for your character_sheet function, you'll need to pass that name to url_for, and then the parameters, like this:
url_for('character_sheet', cha_name=character.name)
If a user were to rename their character, all of the URLs would change, which is a bad user experience — what would happen if they'd bookmarked a particular character, then fixed a typo in the name?
Putting this all together, here's a hopefully-better example:
# app.py
#login_required
#app.route("/<character_id>")
def character_sheet(character_id):
characters = db.execute(
"""SELECT
*
FROM
characters
WHERE
id = :id AND
user_id = :user_id
""",
id=character_id,
user_id=session["user_id"],
)
if not characters:
return abort(404)
return render_template(
"characters/sheet.html",
character=characters[0],
)
<!-- templates/characters/list.html -->
{% extends "main.html" %}
{% block title %}
Characters
{% endblock %}
{% block main %}
<table>
{% for character in characters %}
<tr>
<td>{{ character.name }}</td>
<td><a href={{ url_for('character_sheet', character_id=character.id) }}>View Sheet</a></td>
</tr>
{% endfor %}
</table>
Add a new Character
{% endblock %}

Python/Django: How to show both main model and 'foreign-key model' together in HTML

Good Day SO, I am a beginner in Django and python, just started learning two days ago. Currently, I am trying to do my filtering of data in views.py and creating a context to be shown in my main page that contains both the initial model and the 'foreign-key' model. However, I am having trouble finding help online, even though this is a simple question.. Here goes..
Models involved:
class Plan(models.Model):
plan_ID = models.CharField(
primary_key=True,
max_length=8,
validators=[RegexValidator(regex='^\w{8}$', message='Length has to be 8', code='nomatch')]
)
plan_crisisID = models.ForeignKey(Crisis, on_delete=models.CASCADE)
plan_status = models.CharField(max_length=50)
class Crisis(models.Model):
crisis_ID = models.CharField(
primary_key=True,
max_length=4,
validators=[RegexValidator(regex='^\w{4}$', message='Length has to be 4', code='nomatch')]
)
crisis_name = models.CharField(max_length=50)
Views.py for HTML:
def home(request):
template = loader.get_template('pmoapp/home.html')
crisisList = Crisis.objects.filter(crisis_status='Ongoing').order_by('-crisis_ID')
context = {
'crisisList': crisisList,
#'planList': planList
}
return HttpResponse(template.render(context, request))
And finally, my HTML page:
<tbody>
{% if crisisList %}
{% for crisis in crisisList %}
<tr>
<td>{{ crisis.crisis_ID }}</td>
<td>{{ crisis.crisis_name }}</td>
<td>{{ crisis.crisis_dateTime }}</td>
<td>planid</td>
<td>planstatus</td>
</tr>
{% endfor %}
{% else %}
<p>No crisis available.</p>
{% endif %}
</tbody>
I have several things that I do not know how to do here.. so sorry and bear with me..
As seen above, I am currently only able to show the attributes of the Crisis model, and I do not know how to show the Plan, nor how to filter the data to get the plan with the same crisis ID and highest plan ID
I have a many-to-one relationship between Crisis and Plan, such that a Crisis can have multiple plans, linked by 'Foreign-key': plan_crisisID. I would like for the HTML to show all Crisis objects, and the plan with the highest id value and belonging to the same crisis in the HTML format seen above (planid, planstatus).
I know that the logic portion of this code is done in views.py, however I do not know how to start, or what to do.. Thank you SO for your kind help, I will provide any additional information required.. I have many other similar models with foreign key and many-to-many links and in similar situations.. I hope to learn from answers here so that I can replicate this in other places in my project..
I think that you are on the right track, but should start from the other end because Crisis is on Plan.
In the views pull planlist instead of crisislist, then you can:
<tbody>
{% if planList %}
{% for plan in planList %}
<tr>
<td>{{ plan.crisisID.crisis_ID }}</td>
<td>{{ crisis.crisis_name }}</td>
<td>{{ plan.crisisID.crisis_dateTime }}</td>
<td>{{ plan.plan_ID }}</td>
<td>{{ plan.planstatus }}</td>
</tr>
{% endfor %}
{% else %}
<p>No crisis available.</p>
{% endif %}
</tbody>
Oh and you should probably swap the query to something like:
planList = Plan.objects.filter(crisis_ID__crisis_status='Ongoing').order_by('-crisisID__crisis_ID')

Django: Accessing list attributes in template

I have a SQL query in a Django view and store the results in a variable. As far I know the result should be stored as a list.
def assignments(request):
cursor = connection.cursor()
cursor.execute("SELECT o.article_id, o.amount, m.id, o.create_date, m.status FROM orders o, producers p, machines ma, matches m WHERE ma.producer_id=1 AND m.machine_id = ma.id AND m.order_id = o.id")
articles = cursor.fetchall()
context = {"article_list": articles}
return render(request, 'assignments.html', context)
Then I want to transfer that data row by row in a table in my template.
{% block body %}
<div class="container">
<table class="table">
<thead>...</thead>
<tbody>
{% for articles in article_list %}
<tr>
<td>{{ articles.article_id }}</td>
<td>{{ articles.amount }}</td>
<td>{{ articles.id}}</td>
<td>{{ articles.create_date }}</td>
<td>{{ articles.status }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endblock %}
Unfortunately the table is empty and is not showing any results.
The query itself should be fine. I tested the query in my database workbench and it is showing the correct results.
How can I access the data stored in variable articles from my template?
PS: I'm far from being a programmer. So I don't really know any programming concepts/language.
Any help is highly appreciated. Thanks!
You have a list of lists. Each element in articles_list is just a list of values from the database; it does not have any knowledge of attributes like "id" or "amount".
As Arpit says in the comments, you should be using Django models for this rather than raw SQL.

Categories

Resources