34👍
Ok, so I was curious and went and looked at the source of psycopg2. Turns out I didn’t have to go further than the examples folder 🙂
And yes, this is psycopg2-specific. Basically, if you just want to quote a string you’d do this:
from psycopg2.extensions import adapt
print adapt("Hello World'; DROP DATABASE World;")
But what you probably want to do is to write and register your own adapter;
In the examples folder of psycopg2 you find the file ‘myfirstrecipe.py’ there is an example of how to cast and quote a specific type in a special way.
If you have objects for the stuff you want to do, you can just create an adapter that conforms to the ‘IPsycopgSQLQuote’ protocol (see pydocs for the myfirstrecipe.py-example…actually that’s the only reference I can find to that name) that quotes your object and then registering it like so:
from psycopg2.extensions import register_adapter
register_adapter(mytype, myadapter)
Also, the other examples are interesting; esp. ‘dialtone.py’ and ‘simple.py’.
17👍
I guess you’re looking for the mogrify function.
Example:
>>> cur.mogrify("INSERT INTO test (num, data) VALUES (%s, %s)", (42, 'bar'))
"INSERT INTO test (num, data) VALUES (42, E'bar')"
- [Django]-Django rest framework – filtering for serializer field
- [Django]-Django REST Framework – 405 METHOD NOT ALLOWED using SimpleRouter
- [Django]-What's the difference between returning a `HttpResponseNotFound` and raising a `Http404` in Django?
2👍
You should try to avoid doing your own quoting. Not only will it be DB-specific as people have pointed out, but flaws in quoting are the source of SQL injection bugs.
If you don’t want to pass around queries and values separately, then pass around a list of the parameters:
def make_my_query():
# ...
return sql, (value1, value2)
def do_it():
query = make_my_query()
cursor.execute(*query)
(I probably have the syntax of cursor.execute wrong) The point here is that just because cursor.execute takes a number of arguments, that doesn’t mean you have to handle them all separately. You can deal with them as one list.
- [Django]-How to customize the auth.User Admin page in Django CRUD?
- [Django]-ProgrammingError: relation "django_session" does not exist error after installing Psycopg2
- [Django]-This QueryDict instance is immutable
1👍
This’ll be database dependent (iirc, mysql allows \
as an escape character, while something like oracle expects quotes to be doubled: 'my '' quoted string'
).
Someone correct me if i’m wrong, but the double-quoting method is the standard method.
It may be worth looking at what other db abstraction libraries do (sqlalchemy, cx_Oracle, sqlite, etc).
I’ve got to ask – why do you want to inline the values instead of bind them?
- [Django]-Django update table using data from another table
- [Django]-Create custom buttons in admin change_form in Django
- [Django]-How can i get the running server URL
1👍
Your code snippet would get just like this, according to psycopg extension docs
from psycopg2.extensions import adapt
value = "Unsafe string"
query = "SELECT * FROM some_table WHERE some_char_field = %s;" % \
adapt(value).getquoted()
cursor.execute( query ) # value will be correctly quoted, too
The getquoted
function returns the value
as a quoted and escaped string, so you could also go: "SELECT * FROM some_table WHERE some_char_field = " + adapt(value).getquoted()
.
- [Django]-Proper way to handle multiple forms on one page in Django
- [Django]-How do I get user IP address in Django?
- [Django]-AbstractUser vs AbstractBaseUser in Django?
0👍
This is going to be DB dependent. In the case of MySQLdb, for example, the connection
class has a literal
method that will convert the value to the correct escaped representation for passing to MySQL (that’s what cursor.execute
uses).
I imagine Postgres has something similar, but I don’t think there is a function to escape values as part of the DB API 2.0 spec.
- [Django]-How to access my 127.0.0.1:8000 from Android tablet
- [Django]-Django: Is there a way to keep the dev server from restarting when a local .py file is changed and dynamically loaded?
- [Django]-403 Forbidden error when making an ajax Post request in Django framework
0👍
I don’t think you give any sufficient reasoning behind your avoidance to do this The Right Way. Please, use the APi as it is designed and don’t try so hard to make your code less readable for the next guy and more fragile.
- [Django]-Add rich text format functionality to django TextField
- [Django]-Django : Is it impossible to static tag into block tag?
- [Django]-.filter() vs .get() for single object? (Django)
0👍
PyPika in another good option for building SQL statements. Usage example (based on an example on the project’s homepage):
>>> from pypika import Order, Query
>>> Query.from_('customers').select('id', 'fname', 'lname', 'phone').orderby('id', order=Order.desc)
SELECT "id","fname","lname","phone" FROM "customers" ORDER BY "id" DESC
- [Django]-Users in initial data fixture
- [Django]-Switching from MySQL to Cassandra – Pros/Cons?
- [Django]-How to discriminate based on HTTP method in django urlpatterns
-1👍
If you use django you might want to use the quoting function which is automatically adapted to the currently configured DBMS :
from django.db import backend
my_quoted_variable = backend.DatabaseOperations().quote_name(myvar)
- [Django]-What is the best way to migrate data in django
- [Django]-Django redirect to view
- [Django]-Users in initial data fixture
-3👍
import re
def db_quote(s):
return "\"" + re.escape(s) + "\""
can do the job of simple quoting that works at least with MySQL. What we really need, though is cursor.format() function that would work like cursor.execute() except it would return the resulting query instead of executing it. There are times when you do not want the query to be executed quite yet – e.g you may want to log it first, or print it out for debugging before you go ahead with it.
- [Django]-Django CSRF framework cannot be disabled and is breaking my site
- [Django]-How do I deploy Django on AWS?
- [Django]-How can I change the way a boolean prints in a django template?