diff -r 9c6c09152c06 django/core/management/commands/flush.py
--- a/django/core/management/commands/flush.py	Tue Jan 10 20:54:48 2012 +0600
+++ b/django/core/management/commands/flush.py	Tue Jan 10 21:32:14 2012 +0600
@@ -5,7 +5,7 @@
 from django.core.management import call_command
 from django.core.management.base import NoArgsCommand, CommandError
 from django.core.management.color import no_style
-from django.core.management.sql import sql_flush, emit_post_sync_signal
+from django.core.management.sql import sql_flush, emit_post_sync_signal, emit_pre_sync_signal
 from django.utils.importlib import import_module
 
 
@@ -51,6 +51,7 @@
             confirm = 'yes'
 
         if confirm == 'yes':
+            emit_pre_sync_signal(verbosity, interactive, db)
             try:
                 cursor = connection.cursor()
                 for sql in sql_list:
diff -r 9c6c09152c06 django/core/management/commands/syncdb.py
--- a/django/core/management/commands/syncdb.py	Tue Jan 10 20:54:48 2012 +0600
+++ b/django/core/management/commands/syncdb.py	Tue Jan 10 21:32:14 2012 +0600
@@ -5,7 +5,7 @@
 from django.conf import settings
 from django.core.management.base import NoArgsCommand
 from django.core.management.color import no_style
-from django.core.management.sql import custom_sql_for_model, emit_post_sync_signal
+from django.core.management.sql import custom_sql_for_model, emit_post_sync_signal, emit_pre_sync_signal
 from django.db import connections, router, transaction, models, DEFAULT_DB_ALIAS
 from django.utils.datastructures import SortedDict
 from django.utils.importlib import import_module
@@ -54,6 +54,7 @@
 
         db = options.get('database')
         connection = connections[db]
+        emit_pre_sync_signal(verbosity, interactive, db)
         cursor = connection.cursor()
 
         # Get a list of already installed *models* so that references work right.
diff -r 9c6c09152c06 django/core/management/sql.py
--- a/django/core/management/sql.py	Tue Jan 10 20:54:48 2012 +0600
+++ b/django/core/management/sql.py	Tue Jan 10 21:32:14 2012 +0600
@@ -178,6 +178,18 @@
     return output
 
 
+def emit_pre_sync_signal(verbosity, interactive, db): 
+    # Emit the pre_sync signal for every application. 
+    for app in models.get_apps(): 
+        app_name = app.__name__.split('.')[-2] 
+        if verbosity >= 2:
+            print "Running pre-sync handlers for application", app_name 
+        models.signals.pre_syncdb.send(sender=app, app=app, 
+                                       verbosity=verbosity,
+                                       interactive=interactive, 
+                                       db=db)
+
+
 def emit_post_sync_signal(created_models, verbosity, interactive, db):
     # Emit the post_sync signal for every application.
     for app in models.get_apps():
@@ -187,3 +199,4 @@
         models.signals.post_syncdb.send(sender=app, app=app,
             created_models=created_models, verbosity=verbosity,
             interactive=interactive, db=db)
+
diff -r 9c6c09152c06 django/db/models/signals.py
--- a/django/db/models/signals.py	Tue Jan 10 20:54:48 2012 +0600
+++ b/django/db/models/signals.py	Tue Jan 10 21:32:14 2012 +0600
@@ -11,6 +11,7 @@
 pre_delete = Signal(providing_args=["instance", "using"])
 post_delete = Signal(providing_args=["instance", "using"])
 
+pre_syncdb = Signal(providing_args=["app", "verbosity", "interactive", "db"])
 post_syncdb = Signal(providing_args=["class", "app", "created_models", "verbosity", "interactive"])
 
 m2m_changed = Signal(providing_args=["action", "instance", "reverse", "model", "pk_set", "using"])
diff -r 9c6c09152c06 docs/ref/signals.txt
--- a/docs/ref/signals.txt	Tue Jan 10 20:54:48 2012 +0600
+++ b/docs/ref/signals.txt	Tue Jan 10 21:32:14 2012 +0600
@@ -352,6 +352,42 @@
 
 Signals sent by :doc:`django-admin </ref/django-admin>`.
 
+pre_syncdb
+----------
+
+.. data:: django.db.models.signals.pre_syncdb
+   :module:
+
+Sent by the :djadmin:`syncdb` command before it starts to install an application, and the :djadmin:`flush` command.
+
+Arguments sent with this signal:
+
+``sender``
+    The ``models`` module that was just installed. That is, if
+    :djadmin:`syncdb` just installed an app called ``"foo.bar.myapp"``,
+    ``sender`` will be the ``foo.bar.myapp.models`` module.
+
+``app``
+    Same as ``sender``.
+
+``db``
+    The alias of database on which a command will operate.
+
+``verbosity``
+    Indicates how much information manage.py is printing on screen. See
+    the :djadminopt:`--verbosity` flag for details.
+
+    Functions which listen for :data:`pre_syncdb` should adjust what they
+    output to the screen based on the value of this argument.
+
+``interactive``
+    If ``interactive`` is ``True``, it's safe to prompt the user to input
+    things on the command line. If ``interactive`` is ``False``, functions
+    which listen for this signal should not try to prompt for anything.
+
+    For example, the :mod:`django.contrib.auth` app only prompts to create a
+    superuser when ``interactive`` is ``True``.
+
 post_syncdb
 -----------
 
diff -r 9c6c09152c06 tests/regressiontests/syncdb/__init__.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/regressiontests/syncdb/__init__.py	Tue Jan 10 21:32:14 2012 +0600
@@ -0,0 +1,1 @@
+
diff -r 9c6c09152c06 tests/regressiontests/syncdb/models.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/regressiontests/syncdb/models.py	Tue Jan 10 21:32:14 2012 +0600
@@ -0,0 +1,11 @@
+from django.db import models
+
+
+class Author(models.Model):
+    name = models.CharField(max_length=100)
+
+    class Meta:
+        ordering = ['name']
+
+    def __unicode__(self):
+        return self.name
diff -r 9c6c09152c06 tests/regressiontests/syncdb/tests.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/regressiontests/syncdb/tests.py	Tue Jan 10 21:32:14 2012 +0600
@@ -0,0 +1,77 @@
+from django.db import connections
+from django.db.models import signals
+from django.test import TestCase
+from django.core import management
+
+import models
+
+
+PRE_SYNCDB_ARGS = ['app', 'verbosity', 'interactive', 'db']
+SYNCDB_DATABASE = 'default'
+SYNCDB_VERBOSITY = 1
+SYNCDB_INTERACTIVE = False
+
+
+class PreSyncdbReceiver(object):
+    def __init__(self):
+        self.call_counter = 0
+        self.call_args = None
+
+    def __call__(self, signal, sender, **kwargs):
+        self.call_counter = self.call_counter + 1
+        self.call_args = kwargs
+
+
+class OneTimeReceiver(object):
+    """
+    Special receiver for handle the fact that test runner calls syncdb for
+    several databases and several times for some of them.
+    """
+    
+    def __init__(self):
+        self.call_counter = 0
+        self.call_args = None
+        self.tables = None  # list of tables at the time of the call
+
+    def __call__(self, signal, sender, **kwargs):
+        # Although test runner calls syncdb for several databases,
+        # testing for only one of them is quite sufficient.
+        if kwargs['db'] == SYNCDB_DATABASE:
+            self.call_counter = self.call_counter + 1
+            self.call_args = kwargs
+            connection = connections[SYNCDB_DATABASE]
+            self.tables = connection.introspection.table_names()
+            # we need to test only one call of syncdb
+            signals.pre_syncdb.disconnect(pre_syncdb_receiver, sender=models)
+
+
+# We connect receiver here and not in unit test code because we need to
+# connect receiver before test runner creates database.  That is, sequence of
+# actions would be:
+#   
+#   1. Test runner imports this module.
+#   2. We connect receiver.
+#   3. Test runner calls syncdb for create default database.
+#   4. Test runner execute our unit test code.
+pre_syncdb_receiver = OneTimeReceiver()
+signals.pre_syncdb.connect(pre_syncdb_receiver, sender=models)
+
+
+class SyncdbSignalTests(TestCase):
+    def test_pre_syncdb_call_time(self):
+        self.assertEqual(pre_syncdb_receiver.call_counter, 1)
+        self.assertFalse(pre_syncdb_receiver.tables)
+
+    def test_pre_syncdb_args(self):
+        r = PreSyncdbReceiver()
+        signals.pre_syncdb.connect(r, sender=models)
+        management.call_command('syncdb', database=SYNCDB_DATABASE,
+            verbosity=SYNCDB_VERBOSITY, interactive=SYNCDB_INTERACTIVE)
+        
+        args = r.call_args
+        self.assertEqual(r.call_counter, 1)
+        self.assertItemsEqual(args, PRE_SYNCDB_ARGS)
+        self.assertEqual(args['app'], models)
+        self.assertEqual(args['verbosity'], SYNCDB_VERBOSITY)
+        self.assertEqual(args['interactive'], SYNCDB_INTERACTIVE)
+        self.assertEqual(args['db'], 'default')
