Hi all,

After reading future of QuerySet.extra() 
<https://groups.google.com/forum/#!topic/django-developers/FojuU0syO8Y> 
discussion, 
I was thinking about the current custom ways to tweak SQL queries in 
Django. Firstly, it was the current .extra method, which everyone likely 
wants to get rid of. Secondly, performing raw SQL queries from queryset 
manager or even directly from cursor.
It's really a great approach to perform raw SQL and still receive objects 
of the given model at the end, I think. However, the main disadvantage of 
the current implementation - it's required to type in real table/field 
names, which destroys model's abstraction level (when you never reference 
tables/columns by their real names).
For such cases it's great to have DSL to build SQL queries, but it's a big 
question how low- or high-level language should be. Anyway, it ended up 
with the idea to have SQL templates, similar to current Django HTML 
templates. I even implemented a sample as proof of the concept:

https://github.com/Nepherhotep/django-orm-sugar/blob/exec_sql_template/tests/sql_template_test_app/app/tests.py
https://github.com/Nepherhotep/django-orm-sugar/blob/exec_sql_template/tests/sql_template_test_app/app/templates/select_user_profile.sql

How it works - there is a template "select_user_profile.sql" in a standard 
templates folder:

{% autoescape off %}
SELECT * FROM {{ model }} WHERE {{ model.name }} = {{ search_term }}
{% endautoescape %}

I had to put autoescape tags to prevent quotes in model name converted into 
HTML entities.
A function below should be called somewhere in views:

raw_queryset = exec_sql_template(UserProfile, "select_user_profile.sql", 
{'search_term': 'Bob'})

This function automatically creates a variable "model" (which is actually a 
special model wrapper, which prints table or column names) and passes it 
into template context. To prevent SQL injection, passed params converted 
into %(variable_name)s representation, and escaped automatically by driver. 
Thus the solution above doesn't work with SQLite (as it doesn't support 
named variables).
Also I wanted to automatically provide aliases for all existing models in 
form <app label>.<model name> (not implemented yet):

SELECT *
    FROM
        {{ model }}
    LEFT OUTER JOIN
        {{ myapp.ModelName }} 
    ON
        {{ myapp.ModelName.profile }} = {{ model.pk }}

Almost everything can work out of the box using standard Django templates, 
except quotes converted into entities, unless they don't disabled 
explicitly. Also, not sure if all the databases support 'tablename'.'name' 
syntax to safely define table/column, otherwise wrapper classes should be 
engine dependent.

I don't suggest a concrete implementation, just wanted to get responses of 
the concept.

Regards,
Alexey

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/da716f91-e5ab-466b-8d3e-475cd3738c12%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to