Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get SQL a Django model has (or would call) on .save()

How can you get the SQL for a Django model's .save(), i.e.

from django.db import models

class MyM(models.Model):
   text = models.TextField()

How can you get the SQL that would be created/used in the following scenario:

 >>> m = MyM(text="123")
 >>> m.save()
 # What SQL Django just run?

Thanks!

like image 335
Brian M. Hunt Avatar asked Mar 04 '10 17:03

Brian M. Hunt


People also ask

How can I see SQL query generated by Django?

Documentation and source is available at http://django-debug-toolbar.readthedocs.io/. debug_toolbar is especially useful when you have a query that's failing with a SQL syntax error; it will display the last query that attempted to run (and failed), making it easier to debug.

Which method is used to save a model in db in Python Django?

Saving objects. To save an object back to the database, call save() : Model.

How do I save a query in Django?

Creating objects To create an object, instantiate it using keyword arguments to the model class, then call save() to save it to the database. This performs an INSERT SQL statement behind the scenes. Django doesn't hit the database until you explicitly call save() . The save() method has no return value.

How do I run a SQL query in Django?

Django gives you two ways of performing raw SQL queries: you can use Manager. raw() to perform raw queries and return model instances, or you can avoid the model layer entirely and execute custom SQL directly. Explore the ORM before using raw SQL!


4 Answers

If you want get the insert statement for model before saving - you can use the following code (checked on django 1.4)

from django.db import connection
from django.db.models import sql

def object_to_query(objects):
    if isinstance(objects, (list, tuple)
    values = obj._meta.local_fields
    q = sql.InsertQuery(obj)
    q.insert_values(values, [obj])
    compiler = q.get_compiler('default')
    # Normally, execute sets this, but we don't want to call execute
    setattr(compiler, 'return_id', False)
    stmts = compiler.as_sql()
    stmt = [stmt % params for stmt, params in stmts]
    return stmt[0]
like image 126
Kerrigan Avatar answered Oct 02 '22 14:10

Kerrigan


From the Django FAQ:

How can I see the raw SQL queries Django is running? Make sure your Django DEBUG setting is set to True. Then, just do this:

>>> from django.core.db import db  
>>> db.queries  
[{'sql': 'SELECT polls_polls.id,polls_polls.question,polls_polls.pub_date FROM polls_polls',   
'time': '0.002'}]  

db.queries is only available if DEBUG is True. It's a list of dictionaries in order of query execution. Each dictionary has the following:
sql--The raw SQL statement
time -- How long the statement took to execute, in seconds.
db.queries includes all SQL statements -- INSERTs, UPDATES, SELECTs, etc.

like image 23
DrDee Avatar answered Oct 02 '22 16:10

DrDee


Just run python manage.py sqlall APP_NAME.

like image 25
Oscar Mederos Avatar answered Oct 02 '22 14:10

Oscar Mederos


from django.db.models import sql, Model
from typing import List


def _escape_sql_param(param):
    if type(param) is str:
        return f"'{param}'"
    return str(param)


# noinspection PyProtectedMember
def model_to_insert_sql(models: List[Model]):
    fields = models[0]._meta.local_fields
    q = sql.InsertQuery(models[0])
    q.insert_values(fields, models)

    compiler = q.get_compiler('default')
    # Normally, execute sets this, but we don't want to call execute
    setattr(compiler, 'return_id', False)
    raw_statements = compiler.as_sql()

    mixed_statements = [statement % tuple(_escape_sql_param(param) for param in params)
                        for statement, params in raw_statements]
    return mixed_statements

Then call it such as

model_to_insert_sql([your_model_1, your_model_2])

for a bulk insert. If only want a single insert, call it as

model_to_insert_sql([your_model])

p.s. @Kerrigan's answer cannot compile, and does not work with string types...

like image 33
ch271828n Avatar answered Oct 02 '22 15:10

ch271828n