1
0
mirror of https://github.com/django/django.git synced 2025-07-04 09:49:12 +00:00

[multi-db] Implemented django.core.managment.syncdb using db access through managers. This required changing the progress messages from prospective ('Installing... ') to retrospective ('Installed ... ').

git-svn-id: http://code.djangoproject.com/svn/django/branches/multiple-db-support@3667 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Jason Pellerin 2006-08-27 19:40:49 +00:00
parent 25ecf21fec
commit be589f7034
2 changed files with 60 additions and 73 deletions

View File

@ -280,9 +280,9 @@ def _collate(connection_output, reverse=False):
def syncdb(verbosity=2, interactive=True): def syncdb(verbosity=2, interactive=True):
"Creates the database tables for all apps in INSTALLED_APPS whose tables haven't already been created." "Creates the database tables for all apps in INSTALLED_APPS whose tables haven't already been created."
from django.db import connection, transaction, models, get_creation_module
from django.db.models import signals
from django.conf import settings from django.conf import settings
from django.db import models, transaction
from django.db.models import signals
from django.dispatch import dispatcher from django.dispatch import dispatcher
disable_termcolors() disable_termcolors()
@ -290,76 +290,39 @@ def syncdb(verbosity=2, interactive=True):
# First, try validating the models. # First, try validating the models.
_check_for_validation_errors() _check_for_validation_errors()
# Create missing models for each app
created_models = []
for app_name in settings.INSTALLED_APPS:
# Import the 'management' module within each installed app, to register # Import the 'management' module within each installed app, to register
# dispatcher events. # dispatcher events.
for app_name in settings.INSTALLED_APPS:
try: try:
__import__(app_name + '.management', '', '', ['']) __import__(app_name + '.management', '', '', [''])
except ImportError: except ImportError:
pass pass
data_types = get_creation_module().DATA_TYPES
cursor = connection.cursor()
# Get a list of all existing database tables,
# so we know what needs to be added.
table_list = _get_table_list()
# Get a list of already installed *models* so that references work right.
seen_models = _get_installed_models(table_list)
created_models = set()
pending_references = {}
for app in models.get_apps():
model_list = models.get_models(app)
for model in model_list:
# Create the model's database table, if it doesn't already exist.
if model._meta.db_table in table_list:
continue
sql, references = _get_sql_model_create(model, seen_models)
seen_models.add(model)
created_models.add(model)
for refto, refs in references.items():
try:
pending_references[refto].extend(refs)
except KeyError:
pending_references[refto] = refs
sql.extend(_get_sql_for_pending_references(model, pending_references))
if verbosity >= 2:
print "Creating table %s" % model._meta.db_table
for statement in sql:
cursor.execute(statement)
table_list.append(model._meta.db_table)
for model in model_list:
if model in created_models:
sql = _get_many_to_many_sql_for_model(model)
if sql:
if verbosity >= 2:
print "Creating many-to-many tables for %s model" % model.__name__
for statement in sql:
cursor.execute(statement)
transaction.commit_unless_managed()
# Send the post_syncdb signal, so individual apps can do whatever they need # Send the post_syncdb signal, so individual apps can do whatever they need
# to do at this point. # to do at this point.
for app in models.get_apps(): for app in models.get_apps():
# Install each application (models already installed will be skipped)
created = _install(app, commit=False, initial_data=False)
if verbosity >= 2:
for model in created:
print "Created table %s" % model._meta.db_table
created_models.extend(created)
dispatcher.send(signal=signals.post_syncdb, sender=app, dispatcher.send(signal=signals.post_syncdb, sender=app,
app=app, created_models=created_models, app=app, created_models=created_models,
verbosity=verbosity, interactive=interactive) verbosity=verbosity, interactive=interactive)
transaction.commit_unless_managed()
# Install initial data for the app (but only if this is a model we've # Install initial data for the app (but only if this is a model we've
# just created) # just created)
for app in models.get_apps():
for model in models.get_models(app): for model in models.get_models(app):
if model in created_models: if model in created_models:
initial_sql = get_sql_initial_data_for_model(model)
if initial_sql:
print "Installing initial data for %s model" % model._meta.object_name
try: try:
for sql in initial_sql: if (model._default_manager.load_initial_data()
cursor.execute(sql) and verbosity >= 2):
print "Installed initial data for %s model" % model._meta.object_name
except Exception, e: except Exception, e:
sys.stderr.write("Failed to install initial SQL data for %s model: %s" % \ sys.stderr.write("Failed to install initial SQL data for %s model: %s" % \
(model._meta.object_name, e)) (model._meta.object_name, e))
@ -422,6 +385,11 @@ diffsettings.args = ""
def install(app): def install(app):
"Executes the equivalent of 'get_sql_all' in the current database." "Executes the equivalent of 'get_sql_all' in the current database."
# Wrap _install to hide the return value so ./manage.py install
# doesn't complain about unprintable output.
_install(app)
def _install(app, commit=True, initial_data=True):
from django.db import connection, models, transaction from django.db import connection, models, transaction
import sys import sys
@ -432,20 +400,28 @@ def install(app):
# First, try validating the models. # First, try validating the models.
_check_for_validation_errors(app) _check_for_validation_errors(app)
created_models = []
try: try:
pending = {} pending = {}
for model in models.get_models(app, creation_order=True): for model in models.get_models(app, creation_order=True):
new_pending = model._default_manager.install(initial_data=True) manager = model._default_manager
tables = manager.get_table_list()
models_installed = manager.get_installed_models(tables)
# Don't re-install already-installed models
if not model in models_installed:
new_pending = manager.install(initial_data=initial_data)
created_models.append(model)
for model, statements in new_pending.items(): for model, statements in new_pending.items():
pending.setdefault(model, []).extend(statements) pending.setdefault(model, []).extend(statements)
# execute any pending statements that were waiting for this model # Execute any pending statements that were waiting for this model
if model in pending: if model in pending:
for statement in pending.pop(model): for statement in pending.pop(model):
statement.execute() statement.execute()
if pending: if pending:
for model, statements in pending.items(): for model, statements in pending.items():
tables = model._default_manager.get_table_list() manager = model._default_manager
models_installed = model._default_manager.get_installed_models(tables) tables = manager.get_table_list()
models_installed = manager.get_installed_models(tables)
if model in models_installed: if model in models_installed:
for statement in statements: for statement in statements:
statement.execute() statement.execute()
@ -464,7 +440,9 @@ Hint: Look at the output of 'django-admin.py sqlall %s'. That's the SQL this com
The full error: """ % (app_name, app_name)) + style.ERROR_OUTPUT(str(e)) + '\n') The full error: """ % (app_name, app_name)) + style.ERROR_OUTPUT(str(e)) + '\n')
transaction.rollback_unless_managed() transaction.rollback_unless_managed()
sys.exit(1) sys.exit(1)
if commit:
transaction.commit_unless_managed() transaction.commit_unless_managed()
return created_models
install.help_doc = "Executes ``sqlall`` for the given app(s) in the current database." install.help_doc = "Executes ``sqlall`` for the given app(s) in the current database."
install.args = APP_ARGS install.args = APP_ARGS

View File

@ -130,8 +130,6 @@ class Manager(object):
builder = self.db.get_creation_module().builder builder = self.db.get_creation_module().builder
run, pending = builder.get_create_table(self.model) run, pending = builder.get_create_table(self.model)
run += builder.get_create_indexes(self.model) run += builder.get_create_indexes(self.model)
if initial_data:
run += builder.get_initialdata(self.model)
many_many = builder.get_create_many_to_many(self.model) many_many = builder.get_create_many_to_many(self.model)
for statement in run: for statement in run:
@ -142,8 +140,19 @@ class Manager(object):
statement.execute() statement.execute()
else: else:
pending.setdefault(klass, []).extend(statements) pending.setdefault(klass, []).extend(statements)
if initial_data:
self.load_initial_data()
return pending return pending
def load_initial_data(self):
"""Install initial data for model in db, Returns statements executed.
"""
builder = self.db.get_creation_module().builder
statements = builder.get_initialdata(self.model)
for statement in statements:
statement.execute()
return statements
def get_installed_models(self, table_list): def get_installed_models(self, table_list):
"""Get list of models installed, given a list of tables. """Get list of models installed, given a list of tables.
""" """