开发者

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开发者_StackOverflow社区 SQL Django just run?

Thanks!


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]


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.


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...


Just run python manage.py sqlall APP_NAME.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜