Django raw SQL query using LIKE on PostgreSQL - django

I'm trying to do a Raw SELECT in Django using LIKE in the PostgreSQL database with Psycopg2 driver.
I've tested pretty much what I've found on the web, but nothing have worked.
The situation is the following. I need to perform a SELECT like this:
select distinct on (name, adm1.name, adm2.name_local)
gn.geonameid,
case when altnm.iso_language = 'pt' then altnm.alternate_name else gn.name end as name,
adm1.name as zona,
adm2.name_local as municipio
from location_geonameslocal gn
join location_geonameszone adm1 on adm1.code = gn.country || '.' || gn.admin1
join location_geonamesmunicipality adm2 on adm2.code = gn.country || '.' || gn.admin1 || '.' || gn.admin2
left join location_geonamesalternatenames altnm on altnm.geonameid = gn.geonameid
where
(gn.fclass = 'P' or gn.fclass = 'A')
and (altnm.iso_language = 'pt' or altnm.iso_language = 'link' or altnm.iso_language is null or altnm.iso_language = '')
and gn.country = 'PT'
and (gn.name like '%Lisboa%' or altnm.alternate_name like '%Lisboa%')
order by name, adm1.name, adm2.name_local;
The important/problem part of the SELECT is this one:
and (gn.name like '%Lisboa%' or altnm.alternate_name like '%Lisboa%')
I've write a simple view to test the SELECT, it looks like this:
def get_citiesjson_view(request):
word = "Lisboa"
term = "%" + word + "%"
cursor = connection.cursor()
cursor.execute("select distinct on (name, adm1.name, adm2.name_local)\
gn.geonameid,\
case when altnm.iso_language = 'pt' then altnm.alternate_name else gn.name end as name,\
adm1.name as zona,\
adm2.name_local as municipio\
from location_geonameslocal gn\
join location_geonameszone adm1 on adm1.code = gn.country || '.' || gn.admin1\
join location_geonamesmunicipality adm2 on adm2.code = gn.country || '.' || gn.admin1 || '.' || gn.admin2\
left join location_geonamesalternatenames altnm on altnm.geonameid = gn.geonameid\
where\
(gn.fclass = 'P' or gn.fclass = 'A')\
and (altnm.iso_language = 'pt' or altnm.iso_language = 'link' or altnm.iso_language is null or altnm.iso_language = '')\
and gn.country = 'PT'\
and (gn.name like %s or altnm.alternate_name like %s)\
order by name, adm1.name, adm2.name_local;", [term, term])
data = cursor.fetchone()
mimetype = 'application/json'
return HttpResponse(data, mimetype)
Unfortunately this does not work and I can't find way to make it work. Some clues?
UPDATE: This form is actually working:
cursor.execute("... and (gn.name like %s or altnm.alternate_name like %s)... ", ['%'+term+'%', '%'+term+'%'])

This form is actually working:
cursor.execute("... and (gn.name like %s or altnm.alternate_name like %s)... ", ['%'+term+'%', '%'+term+'%'])

You should not use the default Python formatting to construct SQL query with parameters, to use the raw SQL LIKE clause you could do something like this:
sql = 'SELECT id FROM table WHERE 1 = 1'
params = []
if 'descricao' in args.keys(): # your validation
# build sql query and params correctly
sql += ' AND descricao LIKE %s'
params.append('%'+args['descricao']+'%')
with connections['default'].cursor() as cursor:
cursor.execute(sql, params)
This way you will be safe agaist SQL Injection vulnerability

Related

update_or_create with Django for sum old row

i'm trying to create a row in DATABASE and if exist update the old value to the new + old, with DJANGO. something like PHP above:
$sql= "IF EXISTS(SELECT * FROM April_sales WHERE label='".$product."') THEN
BEGIN
UPDATE francais SET sold=sold+'".$sold."' WHERE label='".$product."';
END;
ELSE
BEGIN
INSERT INTO April_sales (sold,sold) VALUES('".$sold."','".$product."');
END;
END IF;";
i'm receiving new row ,trying this:
query = April_sales.objects.get_or_create(product=product, sold= new_amount, date= timezone.now())
sum_value = query.sold + new_amount
query = April_sales(product=product, sold=sum_value , date=timezone.now())
query.save()
get_or_create of django always returns a tuple, you need two variables to catch what you want:
Try this:
query, created = April_sales.objects.get_or_create(product=product)
if created:
query.sold = new_amount
else:
query.sold += new_amount
query.date = timezone.now()
query.save()
I found the follow solution, it is not pretty and bit long:
if someone has a better suggestion, feel free to improve.
try:
query = April_sales.objects.get(product=product)
query.sold = query.sold + new_amount
query.date = timezone.now()
query.save()
except April_sales.DoesNotExist:
query = April_sales(product=product, sold=new_amount, date=timezone.now())
query.save()

Get data from relational table in odoo

I need to get the data from relational table and check whether the given data is there. I used this code tho do that. Even though there is a search data it gives result as false.
user_category_id = self.env['ir.module.category'].search([('name', '=', 'Company')])
user_new_id = self.env['res.groups'].search(
[('category_id', '=', user_category_id.id),('name','=',"Manager")])
query = """SELECT p.gid from res_groups_users_rel p where p.uid=%d """ % user_id.id
self.env.cr.execute(query)
result = self.env.cr.fetchall()
print result
if user_tiq_id in result:
print "True"
else:
print "false"
Please help me to solve this error
get count instead of select...
user_id= self.env['res.users'].search([('id','=',self.env.user.id)])
user_category_id = self.env['ir.module.category'].search([('name', '=', 'Company')])
user_new_id = self.env['res.groups'].search(
[('category_id', '=', user_category_id.id),('name','=',"Manager")]).id
query = """select COUNT(*) from res_groups_users_rel where uid=%d and gid=%d """ % (user_id.id,user_tiq_id)
self.env.cr.execute(query)
result = self.env.cr.fetchall()
json_result = json.dumps(result, ensure_ascii=False)
count = json_result.strip('\' \" [] ')
str_count = str(count)
int_count = int(str_count)
if int_count==0:
print "fail"
else:
print "pass"

Can you use django extra(select={}) to select multiple fields?

I am trying to add two new fields to my django product queryset and I do something like this
products = Product.objects.filter(company=company).filter(Q(name__icontains=search_term) | Q(code__icontains=search_term))
products = products.extra(select={"is_distributed": product_is_distributed_query(False)})
products = products.extra(select={"expense_type": product_expense_type_query(False)})
But the two queries (product_is_distributed_query and product_expense_type_query) are identical just returning different fields. Can I do this in only one extra(select{}) by using just one query to return both fields?
The query would be like this:
def product_is_distributed_query(use_product_code):
product_query = """
select vt.is_distributed, coalesce(et.name, '')
from (
SELECT
cp.id,
CASE WHEN SUM(coalesce(snp.id, 0)) > 0 THEN true
ELSE false
END as is_distributed,
max(coalesce(snp.expense_type_id, 0)) as maxId1
FROM
core_product AS cp
LEFT JOIN
stock_non_product AS snp
ON (cp.name = snp.name """
product_query = product_query + ("AND cp.code = snp.code" if use_product_code else "")
product_query += """
AND cp.company_id = snp.company_id AND snp.is_deleted = false)
LEFT JOIN expense_type as et ON(snp.expense_type_id = et.id AND snp.company_id = et.company_id)
WHERE
cp.id = core_product.id
AND cp.company_id = core_product.company_id
-- AND snp.company_id = core_product.company_id
GROUP BY
cp.id
) as vt
-- LEFT JOIN stock_non_product AS snp ON(snp.id = maxId)
LEFT JOIN expense_type as et ON(et.id = vt.maxId)
"""
return product_query
instead of being two separated queries that are identical to this one but return one or the other field

Can I trust Django's bulk_create to preserve order?

When I do something like this:
model_list = [Model(name = 'First'), Model(name = 'Second'), Model(name = 'Third')]
Model.objects.bulk_create(model_list)
Can I trust that they will be created in that same order?
That is:
pk1 = Model.objects.get(name = 'First').pk
pk2 = Model.objects.get(name = 'Second').pk
pk3 = Model.objects.get(name = 'Third').pk
(pk3 > pk2) and (pk2 > pk1)
I think you can.
model_list = [Model(name = 'First'),
Model(name = 'Second'),
Model(name = 'Third')]
Model.objects.bulk_create(model_list)
This code will be translated to the following SQL:
INSERT INTO app_model (name) VALUES ('First'), ('Second'), ('Third')
It is very unlikely that regular SQL server will insert these rows in different order.

How to convert a python print function on html

I am trying to use web2py to build an app. I have a simple print function that a user submits a key word . The string or int key word is directed to an sqlite db to retrieve a row and output the data. I need to know
1. how to use the print on html.
2. How to split the string...so far i did the list:string
Here is my code:
def first():
form = SQLFORM.factory(Field('visitor_name',
label = 'Please Type Your keyword here!',
requires= [IS_NOT_EMPTY(), IS_LOWER(),'list:string']))
form.element('input[type=submit]')['_onclick'] = "return \
confirm('Are you sure you want to submit:');"
if form.process().accepted:
session.visitor_name = form.vars.visitor_name
redirect(URL('main'))
return dict(form=form)
def main():
while True:
name = request.vars.visitor_name or redirect(URL('first'))
name2 = name[:]
for item in name2:break
name3 = ' '.join(name2)
import sqlite3
id = 0
location = ""
conn = sqlite3.connect("keywords.db")
c = conn.cursor()
c.execute('select * from kmedicals')
records = c.fetchall()
for record in records:
id = record[0]
location = record[15]
if id == name3:
print name3.capitalize(),':' '\n',location
break
sys.exit()
return dict(name=name)
my view...default/main.html:
{{extend 'layout.html'}}
{{=name}}