Ticket #4528: pre_syncdb_updated.patch
File pre_syncdb_updated.patch, 8.5 KB (added by , 13 years ago) |
---|
-
django/core/management/commands/flush.py
diff -r 9c6c09152c06 django/core/management/commands/flush.py
a b 5 5 from django.core.management import call_command 6 6 from django.core.management.base import NoArgsCommand, CommandError 7 7 from django.core.management.color import no_style 8 from django.core.management.sql import sql_flush, emit_post_sync_signal 8 from django.core.management.sql import sql_flush, emit_post_sync_signal, emit_pre_sync_signal 9 9 from django.utils.importlib import import_module 10 10 11 11 … … 51 51 confirm = 'yes' 52 52 53 53 if confirm == 'yes': 54 emit_pre_sync_signal(verbosity, interactive, db) 54 55 try: 55 56 cursor = connection.cursor() 56 57 for sql in sql_list: -
django/core/management/commands/syncdb.py
diff -r 9c6c09152c06 django/core/management/commands/syncdb.py
a b 5 5 from django.conf import settings 6 6 from django.core.management.base import NoArgsCommand 7 7 from django.core.management.color import no_style 8 from django.core.management.sql import custom_sql_for_model, emit_post_sync_signal 8 from django.core.management.sql import custom_sql_for_model, emit_post_sync_signal, emit_pre_sync_signal 9 9 from django.db import connections, router, transaction, models, DEFAULT_DB_ALIAS 10 10 from django.utils.datastructures import SortedDict 11 11 from django.utils.importlib import import_module … … 54 54 55 55 db = options.get('database') 56 56 connection = connections[db] 57 emit_pre_sync_signal(verbosity, interactive, db) 57 58 cursor = connection.cursor() 58 59 59 60 # Get a list of already installed *models* so that references work right. -
django/core/management/sql.py
diff -r 9c6c09152c06 django/core/management/sql.py
a b 178 178 return output 179 179 180 180 181 def emit_pre_sync_signal(verbosity, interactive, db): 182 # Emit the pre_sync signal for every application. 183 for app in models.get_apps(): 184 app_name = app.__name__.split('.')[-2] 185 if verbosity >= 2: 186 print "Running pre-sync handlers for application", app_name 187 models.signals.pre_syncdb.send(sender=app, app=app, 188 verbosity=verbosity, 189 interactive=interactive, 190 db=db) 191 192 181 193 def emit_post_sync_signal(created_models, verbosity, interactive, db): 182 194 # Emit the post_sync signal for every application. 183 195 for app in models.get_apps(): … … 187 199 models.signals.post_syncdb.send(sender=app, app=app, 188 200 created_models=created_models, verbosity=verbosity, 189 201 interactive=interactive, db=db) 202 -
django/db/models/signals.py
diff -r 9c6c09152c06 django/db/models/signals.py
a b 11 11 pre_delete = Signal(providing_args=["instance", "using"]) 12 12 post_delete = Signal(providing_args=["instance", "using"]) 13 13 14 pre_syncdb = Signal(providing_args=["app", "verbosity", "interactive", "db"]) 14 15 post_syncdb = Signal(providing_args=["class", "app", "created_models", "verbosity", "interactive"]) 15 16 16 17 m2m_changed = Signal(providing_args=["action", "instance", "reverse", "model", "pk_set", "using"]) -
docs/ref/signals.txt
diff -r 9c6c09152c06 docs/ref/signals.txt
a b 352 352 353 353 Signals sent by :doc:`django-admin </ref/django-admin>`. 354 354 355 pre_syncdb 356 ---------- 357 358 .. data:: django.db.models.signals.pre_syncdb 359 :module: 360 361 Sent by the :djadmin:`syncdb` command before it starts to install an application, and the :djadmin:`flush` command. 362 363 Arguments sent with this signal: 364 365 ``sender`` 366 The ``models`` module that was just installed. That is, if 367 :djadmin:`syncdb` just installed an app called ``"foo.bar.myapp"``, 368 ``sender`` will be the ``foo.bar.myapp.models`` module. 369 370 ``app`` 371 Same as ``sender``. 372 373 ``db`` 374 The alias of database on which a command will operate. 375 376 ``verbosity`` 377 Indicates how much information manage.py is printing on screen. See 378 the :djadminopt:`--verbosity` flag for details. 379 380 Functions which listen for :data:`pre_syncdb` should adjust what they 381 output to the screen based on the value of this argument. 382 383 ``interactive`` 384 If ``interactive`` is ``True``, it's safe to prompt the user to input 385 things on the command line. If ``interactive`` is ``False``, functions 386 which listen for this signal should not try to prompt for anything. 387 388 For example, the :mod:`django.contrib.auth` app only prompts to create a 389 superuser when ``interactive`` is ``True``. 390 355 391 post_syncdb 356 392 ----------- 357 393 -
new file tests/regressiontests/syncdb/__init__.py
diff -r 9c6c09152c06 tests/regressiontests/syncdb/__init__.py
- + 1 -
new file tests/regressiontests/syncdb/models.py
diff -r 9c6c09152c06 tests/regressiontests/syncdb/models.py
- + 1 from django.db import models 2 3 4 class Author(models.Model): 5 name = models.CharField(max_length=100) 6 7 class Meta: 8 ordering = ['name'] 9 10 def __unicode__(self): 11 return self.name -
new file tests/regressiontests/syncdb/tests.py
diff -r 9c6c09152c06 tests/regressiontests/syncdb/tests.py
- + 1 from django.db import connections 2 from django.db.models import signals 3 from django.test import TestCase 4 from django.core import management 5 6 import models 7 8 9 PRE_SYNCDB_ARGS = ['app', 'verbosity', 'interactive', 'db'] 10 SYNCDB_DATABASE = 'default' 11 SYNCDB_VERBOSITY = 1 12 SYNCDB_INTERACTIVE = False 13 14 15 class PreSyncdbReceiver(object): 16 def __init__(self): 17 self.call_counter = 0 18 self.call_args = None 19 20 def __call__(self, signal, sender, **kwargs): 21 self.call_counter = self.call_counter + 1 22 self.call_args = kwargs 23 24 25 class OneTimeReceiver(object): 26 """ 27 Special receiver for handle the fact that test runner calls syncdb for 28 several databases and several times for some of them. 29 """ 30 31 def __init__(self): 32 self.call_counter = 0 33 self.call_args = None 34 self.tables = None # list of tables at the time of the call 35 36 def __call__(self, signal, sender, **kwargs): 37 # Although test runner calls syncdb for several databases, 38 # testing for only one of them is quite sufficient. 39 if kwargs['db'] == SYNCDB_DATABASE: 40 self.call_counter = self.call_counter + 1 41 self.call_args = kwargs 42 connection = connections[SYNCDB_DATABASE] 43 self.tables = connection.introspection.table_names() 44 # we need to test only one call of syncdb 45 signals.pre_syncdb.disconnect(pre_syncdb_receiver, sender=models) 46 47 48 # We connect receiver here and not in unit test code because we need to 49 # connect receiver before test runner creates database. That is, sequence of 50 # actions would be: 51 # 52 # 1. Test runner imports this module. 53 # 2. We connect receiver. 54 # 3. Test runner calls syncdb for create default database. 55 # 4. Test runner execute our unit test code. 56 pre_syncdb_receiver = OneTimeReceiver() 57 signals.pre_syncdb.connect(pre_syncdb_receiver, sender=models) 58 59 60 class SyncdbSignalTests(TestCase): 61 def test_pre_syncdb_call_time(self): 62 self.assertEqual(pre_syncdb_receiver.call_counter, 1) 63 self.assertFalse(pre_syncdb_receiver.tables) 64 65 def test_pre_syncdb_args(self): 66 r = PreSyncdbReceiver() 67 signals.pre_syncdb.connect(r, sender=models) 68 management.call_command('syncdb', database=SYNCDB_DATABASE, 69 verbosity=SYNCDB_VERBOSITY, interactive=SYNCDB_INTERACTIVE) 70 71 args = r.call_args 72 self.assertEqual(r.call_counter, 1) 73 self.assertItemsEqual(args, PRE_SYNCDB_ARGS) 74 self.assertEqual(args['app'], models) 75 self.assertEqual(args['verbosity'], SYNCDB_VERBOSITY) 76 self.assertEqual(args['interactive'], SYNCDB_INTERACTIVE) 77 self.assertEqual(args['db'], 'default')