2007-08-16 14:06:55 +08:00
import os
import re
2009-12-22 23:18:51 +08:00
from django . conf import settings
from django . core . management . base import CommandError
from django . db import models
from django . db . models import get_models
def sql_create ( app , style , connection ) :
2007-08-16 14:06:55 +08:00
" Returns a list of the CREATE TABLE SQL statements for the given app. "
2009-12-22 23:18:51 +08:00
if connection . settings_dict [ ' ENGINE ' ] == ' django.db.backends.dummy ' :
2007-08-16 14:06:55 +08:00
# This must be the "dummy" database backend, which means the user
2009-12-22 23:18:51 +08:00
# hasn't set ENGINE for the databse.
2007-08-16 14:06:55 +08:00
raise CommandError ( " Django doesn ' t know which syntax to use for your SQL statements, \n " +
2009-12-22 23:18:51 +08:00
" because you haven ' t specified the ENGINE setting for the database. \n " +
" Edit your settings file and change DATBASES[ ' default ' ][ ' ENGINE ' ] to something like \n " +
2010-10-07 05:10:44 +08:00
" ' django.db.backends.postgresql ' or ' django.db.backends.mysql ' . " )
2007-08-16 14:06:55 +08:00
# Get installed models, so we generate REFERENCES right.
# We trim models from the current app so that the sqlreset command does not
# generate invalid SQL (leaving models out of known_models is harmless, so
# we can be conservative).
2009-11-03 22:02:49 +08:00
app_models = models . get_models ( app , include_auto_created = True )
2007-08-16 14:06:55 +08:00
final_output = [ ]
2008-08-11 20:11:25 +08:00
tables = connection . introspection . table_names ( )
known_models = set ( [ model for model in connection . introspection . installed_models ( tables ) if model not in app_models ] )
2007-08-16 14:06:55 +08:00
pending_references = { }
for model in app_models :
2008-08-11 20:11:25 +08:00
output , references = connection . creation . sql_create_model ( model , style , known_models )
2007-08-16 14:06:55 +08:00
final_output . extend ( output )
for refto , refs in references . items ( ) :
pending_references . setdefault ( refto , [ ] ) . extend ( refs )
2008-03-11 06:18:50 +08:00
if refto in known_models :
2008-08-11 20:11:25 +08:00
final_output . extend ( connection . creation . sql_for_pending_references ( refto , style , pending_references ) )
final_output . extend ( connection . creation . sql_for_pending_references ( model , style , pending_references ) )
2007-08-16 14:06:55 +08:00
# Keep track of the fact that we've created the table for this model.
known_models . add ( model )
# Handle references to tables that are from other apps
# but don't exist physically.
not_installed_models = set ( pending_references . keys ( ) )
if not_installed_models :
alter_sql = [ ]
for model in not_installed_models :
alter_sql . extend ( [ ' -- ' + sql for sql in
2008-08-11 20:11:25 +08:00
connection . creation . sql_for_pending_references ( model , style , pending_references ) ] )
2007-08-16 14:06:55 +08:00
if alter_sql :
final_output . append ( ' -- The following references should be added but depend on non-existent tables: ' )
final_output . extend ( alter_sql )
return final_output
2009-12-22 23:18:51 +08:00
def sql_delete ( app , style , connection ) :
2007-08-16 14:06:55 +08:00
" Returns a list of the DROP TABLE SQL statements for the given app. "
# This should work even if a connection isn't available
try :
cursor = connection . cursor ( )
except :
cursor = None
# Figure out which tables already exist
if cursor :
2008-08-11 20:11:25 +08:00
table_names = connection . introspection . get_table_list ( cursor )
2007-08-16 14:06:55 +08:00
else :
table_names = [ ]
output = [ ]
# Output DROP TABLE statements for standard application tables.
to_delete = set ( )
references_to_delete = { }
2009-11-03 22:02:49 +08:00
app_models = models . get_models ( app , include_auto_created = True )
2007-08-16 14:06:55 +08:00
for model in app_models :
2008-08-11 20:11:25 +08:00
if cursor and connection . introspection . table_name_converter ( model . _meta . db_table ) in table_names :
2007-08-16 14:06:55 +08:00
# The table exists, so it needs to be dropped
opts = model . _meta
Merged the queryset-refactor branch into trunk.
This is a big internal change, but mostly backwards compatible with existing
code. Also adds a couple of new features.
Fixed #245, #1050, #1656, #1801, #2076, #2091, #2150, #2253, #2306, #2400, #2430, #2482, #2496, #2676, #2737, #2874, #2902, #2939, #3037, #3141, #3288, #3440, #3592, #3739, #4088, #4260, #4289, #4306, #4358, #4464, #4510, #4858, #5012, #5020, #5261, #5295, #5321, #5324, #5325, #5555, #5707, #5796, #5817, #5987, #6018, #6074, #6088, #6154, #6177, #6180, #6203, #6658
git-svn-id: http://code.djangoproject.com/svn/django/trunk@7477 bcc190cf-cafb-0310-a4f2-bffc1f526a37
2008-04-27 10:50:16 +08:00
for f in opts . local_fields :
2007-08-16 14:06:55 +08:00
if f . rel and f . rel . to not in to_delete :
references_to_delete . setdefault ( f . rel . to , [ ] ) . append ( ( model , f ) )
to_delete . add ( model )
for model in app_models :
2008-08-11 20:11:25 +08:00
if connection . introspection . table_name_converter ( model . _meta . db_table ) in table_names :
output . extend ( connection . creation . sql_destroy_model ( model , references_to_delete , style ) )
2007-08-16 14:06:55 +08:00
# Close database connection explicitly, in case this output is being piped
# directly into a database client, to avoid locking issues.
if cursor :
cursor . close ( )
connection . close ( )
return output [ : : - 1 ] # Reverse it, to deal with table dependencies.
2009-12-22 23:18:51 +08:00
def sql_reset ( app , style , connection ) :
2007-08-16 14:06:55 +08:00
" Returns a list of the DROP TABLE SQL, then the CREATE TABLE SQL, for the given module. "
2010-12-13 06:58:25 +08:00
# This command breaks a lot and should be deprecated
import warnings
warnings . warn (
' This command has been deprecated. The command ``sqlflush`` can be used to delete everything. You can also use ALTER TABLE or DROP TABLE statements manually. ' ,
2011-04-02 16:37:53 +08:00
DeprecationWarning
2010-12-13 06:58:25 +08:00
)
2009-12-22 23:18:51 +08:00
return sql_delete ( app , style , connection ) + sql_all ( app , style , connection )
2007-08-16 14:06:55 +08:00
2009-12-22 23:18:51 +08:00
def sql_flush ( style , connection , only_django = False ) :
2007-08-26 03:32:30 +08:00
"""
Returns a list of the SQL statements used to flush the database .
2008-11-29 19:51:41 +08:00
2007-08-26 03:32:30 +08:00
If only_django is True , then only table names that have associated Django
models and are in INSTALLED_APPS will be included .
"""
if only_django :
2008-11-29 19:51:41 +08:00
tables = connection . introspection . django_table_names ( only_existing = True )
2007-08-26 03:32:30 +08:00
else :
2008-08-11 20:11:25 +08:00
tables = connection . introspection . table_names ( )
2010-10-31 08:53:58 +08:00
statements = connection . ops . sql_flush (
style , tables , connection . introspection . sequence_list ( )
)
2007-08-16 14:06:55 +08:00
return statements
2009-12-22 23:18:51 +08:00
def sql_custom ( app , style , connection ) :
2007-08-16 14:06:55 +08:00
" Returns a list of the custom table modifying SQL statements for the given app. "
output = [ ]
app_models = get_models ( app )
app_dir = os . path . normpath ( os . path . join ( os . path . dirname ( app . __file__ ) , ' sql ' ) )
for model in app_models :
2009-12-22 23:18:51 +08:00
output . extend ( custom_sql_for_model ( model , style , connection ) )
2007-08-16 14:06:55 +08:00
return output
2009-12-22 23:18:51 +08:00
def sql_indexes ( app , style , connection ) :
2007-08-16 14:06:55 +08:00
" Returns a list of the CREATE INDEX SQL statements for all models in the given app. "
output = [ ]
for model in models . get_models ( app ) :
2008-08-11 20:11:25 +08:00
output . extend ( connection . creation . sql_indexes_for_model ( model , style ) )
2007-08-16 14:06:55 +08:00
return output
2009-12-22 23:18:51 +08:00
def sql_all ( app , style , connection ) :
2007-08-16 14:06:55 +08:00
" Returns a list of CREATE TABLE SQL, initial-data inserts, and CREATE INDEX SQL for the given module. "
2009-12-22 23:18:51 +08:00
return sql_create ( app , style , connection ) + sql_custom ( app , style , connection ) + sql_indexes ( app , style , connection )
2007-08-16 14:06:55 +08:00
2009-12-22 23:18:51 +08:00
def custom_sql_for_model ( model , style , connection ) :
2007-08-16 14:06:55 +08:00
opts = model . _meta
app_dir = os . path . normpath ( os . path . join ( os . path . dirname ( models . get_app ( model . _meta . app_label ) . __file__ ) , ' sql ' ) )
output = [ ]
2008-07-29 13:53:44 +08:00
# Post-creation SQL should come before any initial SQL data is loaded.
2010-01-28 07:48:41 +08:00
# However, this should not be done for models that are unmanaged or
# for fields that are part of a parent model (via model inheritance).
if opts . managed :
post_sql_fields = [ f for f in opts . local_fields if hasattr ( f , ' post_create_sql ' ) ]
for f in post_sql_fields :
output . extend ( f . post_create_sql ( style , model . _meta . db_table ) )
2008-07-29 13:53:44 +08:00
2007-08-16 14:06:55 +08:00
# Some backends can't execute more than one SQL statement at a time,
# so split into separate statements.
statements = re . compile ( r " ;[ \ t]*$ " , re . M )
# Find custom SQL, if it's available.
2009-12-22 23:18:51 +08:00
backend_name = connection . settings_dict [ ' ENGINE ' ] . split ( ' . ' ) [ - 1 ]
sql_files = [ os . path . join ( app_dir , " %s . %s .sql " % ( opts . object_name . lower ( ) , backend_name ) ) ,
2007-08-16 14:06:55 +08:00
os . path . join ( app_dir , " %s .sql " % opts . object_name . lower ( ) ) ]
for sql_file in sql_files :
if os . path . exists ( sql_file ) :
fp = open ( sql_file , ' U ' )
for statement in statements . split ( fp . read ( ) . decode ( settings . FILE_CHARSET ) ) :
# Remove any comments from the file
2008-06-08 13:38:13 +08:00
statement = re . sub ( ur " --.*([ \n \ Z]|$) " , " " , statement )
2007-08-16 14:06:55 +08:00
if statement . strip ( ) :
output . append ( statement + u " ; " )
fp . close ( )
return output
2009-12-22 23:18:51 +08:00
def emit_post_sync_signal ( created_models , verbosity , interactive , db ) :
2007-08-16 14:06:55 +08:00
# Emit the post_sync signal for every application.
for app in models . get_apps ( ) :
app_name = app . __name__ . split ( ' . ' ) [ - 2 ]
if verbosity > = 2 :
print " Running post-sync handlers for application " , app_name
2008-08-06 23:32:46 +08:00
models . signals . post_syncdb . send ( sender = app , app = app ,
created_models = created_models , verbosity = verbosity ,
2009-12-22 23:18:51 +08:00
interactive = interactive , db = db )