Django raw query with WHERE clause generated from previous query - python

I want to do a Django Python MySQL query with WHERE (in sql) being a link generated from a previous query.
Hereby I paste my actual code:
def population(request):
db = MySQLdb.connect(user='xxxx', db='xxxxdb', passwd='xxxxpwd', host='localhost')
cursor = db.cursor()
cursor.execute("SELECT last_name FROM a_population WHERE country='Denmark' ORDER BY last_name")
denominazione_comune = cursor.fetchall();
rows_count = cursor.rowcount
db.close()
counter = 0
return render_to_response('list_last_name.html', {'lastname': last_name}, context_instance=RequestContext(request))
So from this code I get an (un)ordered list of family names. By clicking one of these family names I would like to create another query with the family name clicked as a parameter but I don't have a clue of how to do that.
Thanks a million to whom will give me some input.

Related

SQLAlchemy getting a row using filter() but not with get() function

I'm using SQLAlchemy==1.3.18 and Flask==1.1.2
My problem is that I want to update a row that's inserted using a Stored Procedure. Here is my process:
My engine to the DB:
from sqlalchemy import create_engine
engine = create_engine('mysql+pymysql://db_user:db_password#db_host:db_port')
My model
class Employee(declararive_base()):
__tablename__ = "EMPLOYEE"
id = Column(Integer, primary_key=True)
name = Column(String(30))
last_name = Column(String(30))
I execute a Stored Procedure using this function:
def call_procedure(function_name, params):
connection = cloudsql.Engine.raw_connection()
try:
cursor = connection.cursor()
cursor.callproc(function_name, params)
results = list(cursor.fetchall())
cursor.close()
connection.commit()
return results
finally:
connection.close()
Then, I recover the id of the inserted record and set the value on this variable new_employee_id.
After that I try to execute this: session.query(Employee).get(new_employee_id) and I get None.
But if I do the query using session.query(Employee).filter(Employee.id == new_employee_id).all()
I get the record.
Any ideas about this?
I'm thinking that maybe the get method works over the index and since the table is not reindexed again at that moment, the query cannot get the record. What happens with the filter is that it searches on the whole table and can get the record.
Update: My model class was added to this question.
Update2: I added how I create my engine on SQLAlchemy.

How to populate a dropdown box with a database query instead of a list in flask

this could be a very easy question but as I novice I have to ask here sorry as I have not found the answer so far after a lot of playing with it.
I'm using flask with a python list of food types to allow users to input a food item into a form and have this verified with validators to make sure the item is in the list. The inputted food items from the form then gets stored in a db table.
I wish to replace this list approach with a sql query from a db of pre defined food types, whilst using the SQLAlchemy as this is used elsewhere in the app.
A simplified version of the code is as follows: -
#db connection is already setup and working OK in another part of the app
DB_URL = 'postgresql+psycopg2://{user}:{pw}#{url}:{port}/{db}'.format(user=POSTGRES_USER, pw=POSTGRES_PW, url=POSTGRES_URL, port=POSTGRES_PORT, db=POSTGRES_DB)
app.config['SQLALCHEMY_DATABASE_URI'] = DB_URL
db = SQLAlchemy(app)
#example of the list
eaten = ['bread', 'crackers', 'ham', 'bacon']
#where the 'food_word' variable gets defined from an input and validated
food_word_1 = StringField('add the food type you have eaten here:', validators=[Optional(), AnyOf(eaten)])
I've tried replacing the list with eaten = db.execute('SELECT food_name FROM food_type') (table & column) with no luck.
I'm not sure if I need to create some kind of class/methods in the model.py for this Select/GET operation or even use something like pandas (which I also have in the app) to do this job.
Any guidance appreciated!
thanks, md
SQLAlchemy is an Object Relational Mapper. It helps to interact with the database without SQL query. It is an abstraction to the database. So you should not write SQL query here. Rather you have to create an inherited class from db.Model. Like below.
class FoodType(db.Model):
id = db.Column(db.Integer, primary_key=True)
food_name = db.Column(db.String(120), unique=True, nullable=False)
def __repr__(self):
return '<User %r>' % self.food_name
Then for fetching data, you have to call the query function,
db.query.all()
# or
db.query.filter_by()
The result will be a single list.
If you using postgres directly, without SQLAlchemy, then SQL query will be like,
>>> conn = psycopg2.connect(DATABASE_URL)
>>> cur = conn.cursor()
>>> cur.execute('SELECT food_name FROM food_type')
>>> cur.fetchall()
[['bread'], ['crackers'], ['ham'], ['bacon']]
If you want to convert as a single list,
eaten = [i[0] for i in db.fetchall()]

How to show different data to different users in flask application?

I have created a flask application and using mysql as DB backend and this is used by multiple users simultaneously.
The problem I'm having is,In my homepage a select query is performed and data is displayed to the user but same data is showing to all users.it should be unique. I have tried to lock the row by using FOR UPDATE while selecting the row. I know that I'm not updating the row,so the transaction will be closed when the function ends and the row will be released from lock.
How to overcome this problem?
Expected output: Each user should get different data from the table.(Even when they refresh)
#is_logged_in
#app.route('/')
def index():
conn = mysql.connection
cur = conn.cursor()
cur.execute("select mylist ,myurl ,swatch,parent from image_links where status =%s LIMIT 1 FOR UPDATE",("fetched",))
parent = cur.fetchall()
for row in parent:
mylistitems = row[0].split(",")
swatches = row[2].split(",")
myurlsitems = row[1].split(",")
pid = row[3]
if asinlist != ['']:
merged = tuple(zip(mylistitems ,myurlsitems ,swatches))
return render_template('home.html',firstimage= myurlsitems[0],merged=merged)
else:
cur.execute("UPDATE asin_links SET status = %s WHERE pid= %s", ("invalid",pid,))
conn.commit()
return redirect(url_for('index'))
I can't see any "current user" specific parameters used in your sql query or any data filtering decided on some user ID.
Basically, if you are running the same code, same query for all requests on this endpoint, it will never be really unique. You need to add some user specific checks so you can differentiate the output for the current requesting user.
Depending on your use-case and database models, if the data in the table image_links is also created/inserted by some user action you might want additionally save some user ID alongside these values, eg. by extending the table model with another "user_id" column and on insert also add the id of the current user.
You are using some auth decorator #is_logged_in, if you are already handling users in some table then the another user_id column could be a reference to the respective user's primary key. Then, in your example, you would just add additional where user_id = check with the current user's primary key.
As I see in this SQL query:
SELECT mylist, myurl, swatch, parent FROM image_links WHERE status
perhaps you did specify the related user to get its own specific data, try to replace that last "where" with:
WHERE id = (user.id) --> user object
or you could use the AND keyword, something like
WHERE status = (x) AND id = (y)

SQL Query returning "None" instead of row

I'm working on a light login, and have a tabled titled Users. I'm trying to take my login form POST body and verify it across the database.
Values from form:
user = request.form['username']
password = request.form['password']
SQL Statement:
conn = sqlite3.connect(db)
cur = conn.cursor()
cur.execute("SELECT * FROM Users WHERE Username LIKE '(%s)'" % user)
row = cur.fetchone()
Users Table:
So on a POST request from my form, here is what is printed:
Print(user, password) = ph104694 Password123
Print(row) = None
So you can see the row is being returned as None when the data absolutely exists. If I change user to something I know is incorrect, I'm getting the same results, but if I change the table from Users to something like Users2 I'm met with a no table exists error which is fine. So despite matching data existing something about my statement isn't allowing it to produce that row. Any ideas?
You're search expression is evaluating to (ph104694) which clearly doesn't exist in the data you showed.
There is no reason to use the LIKE operator here and it probably runs counter to what you want to do (match the single record exactly matching the user ID that was entered).
This is the classic example of code that is subject to an SQL injection attack. You should never, never, ever use string interpolation to build an SQL string like this. Instead, use parameter substitution.
Taken all together, you want something like this:
cur.execute("SELECT * FROM Users WHERE Username = ?", [user])
Your query string evaluates to "SELECT * FROM Users WHERE Username LIKE '(ph104694)'".
Note the parentheses which aren't in the actual username.
Also, you almost certainly don't want to use LIKE.
What you want is "SELECT * FROM Users WHERE Username = 'ph104694'"
Which would create with "SELECT * FROM Users WHERE Username = '{user}'".format(user=user)
Also, you can (and should) parameterize this as
cur.execute("SELECT * FROM Users WHERE Username = :user", {user: user})

Cannot make views of views

Using Python I try to access a view of a view:
import sqlite3
conn = sqlite3.connect("test.db")
mydb = conn.cursor()
mydb.execute("CREATE TABLE TestTbl (MRTarget_id int, Fullmodel text)")
mydb.execute("CREATE TABLE TestTbl2 (Other_id int, Othermodel text)")
mydb.execute("CREATE VIEW TestView AS SELECT m.ROWID, m.MRTarget_id, m.Fullmodel, t.Othermodel FROM TestTbl m, TestTbl2 t")
mydb.execute("CREATE VIEW TestView2 AS SELECT m.Fullmodel, m.Othermodel FROM TestView m")
mydb.close()
Attempting to create TestView2, I get an error:
sqlite3.OperationalError: no such column: m.Fullmodel
Above SQL statements work fine from SQLite prompt. The database contains views of views; could it be that it is not possible to access these using Python?
I've had the same problem - and I found a solution. I believe your problem is that in your initial view 'TestView', the attribute names are actually m.ROWID, m.Fullmodel etc instead of just ROWID, Fullmodel etc.
A casual look at the views through sqlite manager won't reveal the m. appended to the front of each field name. If you run the Pragma query PRAGMA table_info TestView, the attribute extensions will be revealed.
So, change your TestView creation query to
CREATE VIEW TestView AS
SELECT m.ROWID as ROWID, m.MRTarget_id as MRTarget_id,... etc
and your second Create View query should run successfully - at least it did in my application.
Your code works fine for me.
You could try committing between creating the first view and the second:
conn.commit()

Categories

Resources