CS50 Finance History Problem with SQL SELECT - sql

I don't understand why I can't SELECT the 'transaction' column from my TABLE portfolio. I created a TABLE using the syntax below:
CREATE TABLE 'portfolio' ('transaction' integer primary key autoincrement,
'datetime' datetime, user_id bigint, 'symbol' varchar(5), 'price' numeric(8,
2), 'shares' integer, 'total' numeric(8, 2));
The transaction keeps a running count of buy/sell orders. When I have transaction in the SELECT statement, it gives me an error, see below:
RuntimeError: near "transaction": syntax error [SQL: 'SELECT transaction,
datetime, symbol, shares, price FROM portfolio WHERE user_id = 2']
(Background on this error at: http://sqlalche.me/e/e3q8)
If I don't include transaction in the python code, then everything works and the table is displayed on the webpage. What is preventing me from selecting transaction? In the code, I included transaction.
#app.route("/history")
#login_required
def history():
"""Show history of transactions"""
#create table
history = db.execute("SELECT transaction, datetime, symbol, shares, price FROM portfolio WHERE user_id = :user_id", user_id = session["user_id"])
history_info = []
for info in history:
transaction = info["transaction"]
datetime = info["datetime"]
symbol = info["symbol"]
shares = info["shares"]
price = info["price"]
total = abs(shares * price)
history_info.append({"transaction":transaction, "datetime":datetime, "symbol":symbol, "shares":shares, "price":price, "total":total})
return render_template("history.html", history_info = history_info)
The html below is what will be displayed on the webpage. Currently, I left off the transaction.
{% extends "layout.html" %}
{% block title %}
History
{% endblock %}
{% block main %}
<table class="table table-bordered">
<thead>
<th>Purchase Date/Time</th>
<th>Symbol</th>
<th>Shares</th>
<th>Price</th>
<th>Total</th>
</thead>
<tbody>
{% for stock in history_info %}
<tr>
<td>{{ stock.datetime }}</td>
<td>{{ stock.symbol }}</td>
<td>{{ stock.shares }}</td>
<td>{{ stock.price }}</td>
<td>{{ stock.total }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}

Resolved....
transaction is a reserved word.
Try putting it in brackets [transaction] and see if that works for you.

Related

Flask SqlAlchemy DB2 SQLALCHEMY_DATABASE_URI

i'm trying to figure out the Uri string to connect correctly to db2 using flask with SqlAlchemy.
I've tried with
db2:///?Server=server&;Port=50000&User=admin&Password=admin&Database=test"
'ibm_db_sa+pyodbc400://{username}:{password}#{host}:{port}/{database};currentSchema={schema}
Any clue for the correct value?
Just for the record the correct format (at least for me) is
ibm_db_sa://{username}:{password}#{host}:{port}/{database}
Also you need a few libraries to install via pip in order to work with alembic+flask
ibm_db
ibm_db_sa
ibm_db_alembic (https://pypi.org/project/ibm_db_alembic/)
In the ibm_db_alembic document is a typo in the description usage, the correct one to import is
from ibm_db_alembic.ibm_db import IbmDbImpl
Here is a simple example:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'ibm_db_sa://enter_user:enter_password#enter_host:50000/BLUDB'
# for secure
# app.config['SQLALCHEMY_DATABASE_URI'] = 'ibm_db_sa://enter_user:enter_password#enter_host:50001/BLUDB;SECURITY=SSL;sslCertLocation=path/to/cer_file.cer;sslConnection=true;'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
class User(db.Model):
__tablename__ = 'enter_table_name'
__table_args__ = {"schema":"enter_shema_name"}
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(256), index=True)
age = db.Column(db.Integer, index=True)
address = db.Column(db.String(256))
phone = db.Column(db.String(256))
email = db.Column(db.String(256))
db.create_all()
If you need to generate fake data for the test, you can do it with the following piece of code:
from faker import Faker
def create_fake_users(n):
"""Generate fake users."""
faker = Faker()
for i in range(n):
user = User(name=faker.name(),
age=random.randint(20, 80),
address=faker.address().replace('\n', ', '),
phone=faker.phone_number(),
email=faker.email())
db.session.add(user)
db.session.commit()
print(f'Added {n} fake users to the database.')
And then the generated data can be sent to display in your template:
#app.route('/')
def index():
users = User.query
return render_template('your_template.html', title='Fake Users',
users=users)
And you can easily display the content in block content
{% block content %}
<table id="data" class="table table-striped">
<thead>
<tr>
<th>Name</th>
<th>Age</th>
<th>Address</th>
<th>Phone Number</th>
<th>Email</th>
</tr>
</thead>
<tbody>
{% for user in users %}
<tr>
<td>{{ user.name }}</td>
<td>{{ user.age }}</td>
<td>{{ user.address }}</td>
<td>{{ user.phone }}</td>
<td>{{ user.email }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}

Obtaining an item count from a list in a Django template

I am trying to get the object count on a 'list' using the length filter in the Django template and it is returning the number of characters. It looks like my list is not a real list but rather a long string. My mixin looks like this:
class ItemObjectMixin:
model = None
template_name = None
my_filter = ItemFilter
def get(self, request):
items = self.model.objects.all()
items_count = items.count()
itemsFilter = ItemsFilter(request.GET, queryset=items)
items = itemsFilter.qs
remaining = items.count()
return render(request, self.template_name, locals())
And my class-based view looks like:
class MyItemsListView(ItemObjectMixin, ListView):
model = Items
template_name = "Items/myItems.html"
My template has the following partial code:
<tbody>
{% for item in items %}
<tr>
<td>{{ item.title }}</td>
<td>{{ item.id }}</td>
{% if item.group_of_items %}
<td>{{ item.group_of_items|length }}</td>
{% endif %}
<td>{{ item.group_of_items }}</td>
</tr>
{% endif %}
</tbody>
The code {{ item.group_of_items|length }} gives the number of characters for each instance of 'group_of_items'. I understand why this is happening but would like a solution where the for loop gives a list of objects rather than a string. Any takers? Cheers.

How to insert variable parameter to SQL stored procedure in Flask app

I am looking for some advice for my Flask app. I want for a user to be able to click on a name of a product and when they click, it brings user to a new page with table of historical orders for that specific item. I have looked at these two questions (and more) but they don't seem to have the answer I'm looking for.
Table Variable As a parameter In My sql Stored Procedures
how to pass output parameter to ms-sql stored procedure using knex.
In my app.py file, I have the following stored procedure -
order_history = '''exec Web_ProductHistory ?'''
And here is the associated route and function for it -
#app.route('/prev-orders/')
def previous_orders():
ItemID = request.form.get('ItemID')
cursor = cnxn.cursor()
cursor.execute(order_history, (ItemID))
data = cursor.fetchall()
return render_template('previous-orders.html', data=data)
I have a table filled with stock items working and here is the table -
{% for value in data %}
<tr>
<td class="hidden"></td>
<td></td>
<td><span style="margin-left: 40px">{{ value[1] }}</span></td>
<td><a name="{{ value[0] }}" class="black-text" href="{{url_for('previous_orders')}}" target="_blank">{{ value[3] }}</a></td>
<td>{{ value[12] }}</td>
<td>{{ value[23] }}</td>
<td class="over-25">{{ value[18] }}</td>
<td>{{ value[6] }}</td>
<td>{{ value[7] }}</td>
<td><a name="{{ value[0] }}" class="black-text" href="{{url_for('live_so')}}" target="_blank">{{ value[14] }}</a></td>
<td>{{ value[16] }}</td>
<td>{{ value[15] }}</td>
<td>{{ value[22] }}</td>
<td>{{ value[2] }}</td>
</tr>
{% endfor %}
value[0] is the ItemID integer.
So far, I have tried to change the route to #app.route('/prev-orders/') or #app.route('/prev-orders/ItemID') but that doesn't do it. I then tried to change the second line to
def previous_orders(ItemID) but that doesn't get it working either.
Have you any tips for me to try to get this working? Thanks!
request.form.get('ItemID')
This expects the ItemID to be posted. If you want to pass it within the URL, then do something like:
#app.route('/prev-orders/<integer:ItemID>')
def previous_orders(ItemID):
cursor = cnxn.cursor()
# ... rest of code
Then generate the link in your HTML with:
{{ value[3] }}
Also, as a side note, I think the following line should be:
cursor.execute(order_history, (ItemID,))
(note the extra comma which makes that second argument a valid tuple, which I think is what the execute method expects)

Twig: Finding the sum of values of rows in column

How do I find the total value of all the rows in a column with Twig? For example I have a column "QTY" that will list number of quantities of each row, I want the sum of the total ROWS of QTY (not the sum of qty). What is the tag/logic in Twig?
I have something like this:
<table class="tablesorter">
<thead>
<th>DA</th>
<th>Part</th>
<th>Batch</th>
<th>Qty</th>
</thead>
{% for getbatches in getbatch %}
<tr>
<td>{{getbatch.dano}}</td>
<td>{{getbatch.partno}}</td>
<td class="highlight">{{getbatch.batchno}}</td>
<td>{{getbatch.inqty}}</td>
</tr>
{% endfor %}
</table>
For the rows that populate, I would like the count of the column of QTY, or any column.
Base on your code and according to that you want to get Count of rows in Qty column you can try
<table class="tablesorter">
<thead>
<th>DA</th>
<th>Part</th>
<th>Batch</th>
<th>Qty</th>
</thead>
{% set row_count = 0 %}
{% for getbatches in getbatch %}
<tr>
<td>{{getbatch.dano}}</td>
<td>{{getbatch.partno}}</td>
<td class="highlight">{{getbatch.batchno}}</td>
<td>{{getbatch.inqty}}</td>
</tr>
{% set row_count = row_count + 1 %}
{% endfor %}
</table>
if you want to show that amount somewhere (like a span) you can use <span>{{ row_count }}</span> after
UPDATED
A better solution to show the rows count anywhere if your twig template might be just showing the count of getbatches:
<span>Row count: </span><span>{{ getbatches is defined ? getbatches|length : 0 }}</span>
If you print rows of a table in twig and wany to get the "count of rows in QTY column", you should pass this data to twig from doing a simple count() on the array of rows. If you want to do it "the hard way", you could do:
{% set numRows = 0 %}
{% for .... %}
{% set numRows = numRows + 1 %}
{% endfor %}
but as #TheLittlePig said, twig's purpose is to display data, not do calculations

Django: Grouping by Dates and Servers

So I am trying to emulate google app's status page: http://www.google.com/appsstatus#hl=en but for backups for our own servers. Instead of service names on the left it'll be server names but the dates and hopefully the pagination will be there too. My models look incredibly similar to this:
from django.db import models
STATUS_CHOICES = (
('UN', 'Unknown'),
('NI', 'No Issue'),
('IS', 'Issue'),
('NR', 'Not Running'),
)
class Server(models.Model):
name = models.CharField(max_length=32)
def __unicode__(self):
return self.name
class Backup(models.Model):
server = models.ForeignKey(Server)
created = models.DateField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
status = models.CharField(max_length=2, choices=STATUS_CHOICES, default='UN')
issue = models.TextField(blank=True)
def __unicode__(self):
return u'%s: %s' % (self.server, self.get_status_display())
My issue is that I am having a hell of a time displaying the information I need. Everyday a little after midnight a cron job will run and add a row for each server for that day, defaulting on status unknown (UN).
My backups.html:
{% extends "base.html" %}
{% block content %}
<table>
<tr>
<th>Name</th>
{% for server in servers %}
<th>{{ created }}</th>
</tr>
<tr>
<td>{{ server.name }}</td>
{% for backup in server.backup_set.all %}
<td>{{ backup.get_status_display }}</td>
{% endfor %}
</tr>
{% endfor %}
</table>
{% endblock content %}
This actually works but I do not know how to get the dates to show. Obviously {{ created }} doesn't do anything but the servers don't have create dates. Backups do and because it's a cron job there should only be X number of rows with any particular date (depending on how many servers we are following for that day).
Summary
I want to create a table, X being server names, Y being dates starting at today while all the cells being the status of a backup. The above model and template should hopefully give you an idea what my thought process but I am willing to alter anything. Basically I am create a fancy excel spreadsheet.
I suggest adding a function to get the dates you want to show, that's independent of a Server instance. Then you can use it both to get the recent backups and to get the dates for the header. In models.py:
from django.db import models
import datetime
def recent_dates():
return [datetime.date.today() - datetime.timedelta(days=days)
for days in range(-6, 1)]
class Server(models.Model):
...
def backup_for_date(self, date):
next_date = date + datetime.timedelta(days=1)
return self.backup_set.get(created__gte=date, created__lt=next_date)
def recent_backups(self):
return [self.backup_for_date(date) for date in recent_dates()]
Then, if you use the function in views.py:
from django.shortcuts import render_to_response
from myapp.models import Server, recent_dates
def status(request):
servers = Server.objects.all()
return render_to_response('status.html',
{'dates': recent_dates(), 'servers': servers}
)
...you can use the recent_dates variable to print the headers in the template:
{% extends "base.html" %}
{% block content %}
<table>
<tr>
<th>Name</th>
{% for date in recent_dates %}
<th>{{ date }}</th>
{% endfor %}
</tr>
{% for server in servers %}
<tr>
<td>{{ server.name }}</td>
{% for backup in server.recent_backups() %}
<td>{{ backup.get_status_display }}</td>
{% endfor %}
</tr>
{% endfor %}
</table>
{% endblock content %}
Using this method also makes sure the cells don't get shifted out of position if data is missing. The code I provided will raise an exception in the call to the get() method inside backup_for_date() if data is missing, but backup_for_date() could easily be modified to return None in that case.