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)
Related
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})
if is_admin == True:
admin_users = Group(name = 'Admin')
try:
admin_users.save()
except:
log.info("Admin Group already exists")
pass
group_id = Group.objects.get(name='Admin').id
If in the data that I get 'is_admin' is true then I will create the group 'Admin' if not existed then save it and fetches the id of that group-'Admin'. This id will be saved in the userinfo with Group as a foreign key.
The following query should give me the id of that group.
group_id = Group.objects.get(name='admin').id
Instead it is saying
current transaction is aborted, commands ignored until end of transaction block
I am using the postgresql database I don't know why it is giving me the error while executing this query. Please tell me how to write the query.
What are you trying to achieve is already in django: get_or_create. Using this your code should look like
group, created = Group.objects.get_or_create(name='Admin')
if created:
log.info("Admin Group already exists")
group_id = group.pk
pk is a convenience property on all django models that always point to a primary key field, no matter if it's autocreated or specified explicitly.
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.
I am using sql alchemy in my project.
I have one problem when two or more tables are joined or have foreign key relation then i am unable to query on joined tables attribute in where condition.
Eg. I have notice table and a user table user.id is foreign key of notice.sender
now I want to search notice by user.name
notice table:[id, sender(FK user.id), receiver(FK user.id), subject, message, status]
user table: [id, name, email, address, status]
Join in notice model:
sender_user = relationship('User', primaryjoin='Notice.sender==user.id', backref=backref("sender_user"))
receiver_user = relationship('User', primaryjoin='Notice.receiver==user.id', backref=backref("receiver_user"))
SQL alchemy filter query:
user_name='john'
notice=db_session.query(Notice)
notice = notice.filter(Notice.sender_user.name == user_name)
Following query doesn't works:
notice=db_session.query(Notice)
notice = notice.filter(Notice.user.name == user_name)
Please help!
You need to acquire a session object, then do:
query = session.query(Notice).filter(Notice.sender_user.name == user_name)
results = query.all()
If that does not work (you don't get the results you expect), try doing this:
session.query(Notice, User.name).filter((Notice.sender_user.id == User.id) & (User.name == user_name))
results = query.all()
I suppose you also have a field called sender which is the id of the user. Then, this should also work:
session.query(Notice, User.name).filter((Notice.sender == User.id) & (User.name == user_name))
Retry all of them, I made some small modifications. (you can see them in revision history). It would be weird if they don't work... (If they don't, try posting the question on the SQLAlchemy mailing list)
I have written code for managing conditional insert/update/delete to
multiple tables from single form in 'web2py'.
I agree, the code is in very raw form & may not be ‘pythonic’.
There are code repeatitions.
But at least I have something to go ahead & build a refined
structure.
MODELS:
db.define_table('mdlmst',
Field('mdlmstid','id'),
Field('mdlmstcd'),
Field('mdlmstnm'),
migrate=False,
format='%(mdlmstnm)s'
)
db.define_table('wrmst',
Field('wrmstid','id'),
Field('wrmstcd'),
Field('wrmstnm'),
migrate=False,
format='%(wrmstnm)s'
)
db.define_table('extwrmst',
Field('extwrmstid','id'),
Field('extwrmstcd'),
Field('extwrmstnm'),
migrate=False,
format='%(extwrmstnm)s'
)
from the FORM, data will be populated in the following two tables
db.define_table('mdlwr',
Field('mdlwrid','id'),
Field('mdlmstid',db.mdlmst),
Field('wrmstid',db.wrmst),
migrate=False
)
db.define_table('mdlextwr',
Field('mdlextwrid','id'),
Field('mdlmstid',db.mdlmst),
Field('extwrmstid',db.extwrmst),
migrate=False
)
CONTROLLERS:
‘modelwar’ controller will render the records from ‘mdlmst’ table
def modelwar():
models = db(db.mdlmst.mdlmstid>0).select(orderby=db.mdlmst.mdlmstnm)
return dict(models=models)
after clicking a particular record, ‘war_edit’ controller will
manage the tables – ‘mdlwr’ & ‘mdlextwr’
def war_edit():
mdl_id = request.args(0)
mdl_id is a variable identifying the ‘mdlmstid’ (which record to be modified)
mdl_nm = request.args(1)
mdl_nm is a variable for getting the ‘mdlmstnm’
warset = db(db.mdlwr.mdlmstid==mdl_id) # fetch a set
extwarset = db(db.mdlextwr.mdlmstid==mdl_id) # fetch a set
warlist = db(db.mdlwr.mdlmstid==mdl_id).select() # get a ROW object
extwarlist = db(db.mdlextwr.mdlmstid==mdl_id).select() # get a ROW object
form_war=FORM(TABLE(TR("Basic Warranty",
SELECT(_type="select",_name="baswar",*[OPTION(x.wrmstnm,_value=x.wrmstid)
for x in db().select(db.wrmst.ALL)]),
TR("Extended Warranty",
SELECT(_type="select",_name="extwar",*[OPTION(x.extwrmstnm,_value=x.extwrmstid)
for x in db().select(db.extwrmst.ALL)]),
TR("", INPUT(_type='submit',_value='Save')), ))))
pre-populate the fields in‘form_war’
if len(warlist)>0:
form_war.vars.baswar = warlist[0].wrmstid
if len(extwarlist)>0:
form_war.vars.extwar = extwarlist[0].extwrmstid
after successful form submission, manage the table 'mdlwr'
if form_war.accepts(request.vars, session):
if there was any record in the list fetched from database & sent to FORM,
if len(warlist)>0:
delete if value returned from FORM field is blank, else update
if form_war.vars.baswar==''
warset.delete()
else:
warset.update(wrmstid=form_war.vars.baswar)
else insert
else:
db.mdlwr.insert(mdlmstid=mdl_id, wrmstid=form_war.vars.baswar)
Similarly, manage the table 'mdlextwr'
if len(extwarlist)>0:
if form_war.vars.extwar=='':
extwarset.delete()
else:
extwarset.update(extwrmstid=form_war.vars.extwar)
else:
db.mdlextwr.insert(mdlmstid=mdl_id, extwrmstid=form_war.vars.extwar)
response.flash = 'Warranty definition saved'
return dict(form_war=form_war,mdlnm=mdl_nm)
VIEW for 'mdlmst' table
{{response.files.append(URL(r=request,c='static',f='jquery.dataTables.min.j
s'))}}
{{response.files.append(URL(r=request,c='static',f='demo_table.css'))}}
{{extend 'layout.html'}}
jQuery(document).ready(function()
{ jQuery('.smarttable').dataTable();});
Modelwise Warranty Master
Model IDModel CodeModel Name
{{for model in models:}}
{{=model.mdlmstid}}
{{=model.mdlmstcd}}
{{=model.mdlmstnm}}
{{=A('edit
warranty',_href=URL('war_edit',args=[model.mdlmstid,model.mdlmstnm]))}}
{{pass}}
Pl. tell me if I have coded anything stupid here.
I would highly welcome any ideas/suggestions for improvements.
Thanks,
Vineet
Your database design looks strange to me.
In each table you have a field of type 'id'. This will replace the id field automatically generated by web2py - a bad idea. From the web2py book: "Do not declare a field called "id", because one is created by web2py anyway. Every table has a field called "id" by default. It is an auto-increment integer field (starting at 1) used for cross-reference and for making every record unique, so "id" is a primary key"
You have created a many to many relationship between table 'mdlmst' and 'wrmst' and another many to many relationship between 'mdlmst' and 'extwrmst'. While this is not necessarily wrong, it strikes me as extremely unlikely this is what you want.
My feeling is that your database design needs work. This should be sorted out before you start designing forms.