Ticket #2225: sql_patch.diff

File sql_patch.diff, 12.3 KB (added by glassresistor, 5 years ago)

Patch which addes a new BaseCommand? based off of AppCommand? called CrossAppCommand? which allows multiple applications transparent access to the models of other app and matches sql printout to syncdb, fix is extended to the other sql management commands

  • django/core/management/commands/sqlall.py

     
    1 from django.core.management.base import AppCommand
     1from django.core.management.base import CrossAppCommand
    22
    3 class Command(AppCommand):
     3class Command(CrossAppCommand):
    44    help = "Prints the CREATE TABLE, custom SQL and CREATE INDEX SQL statements for the given model module name(s)."
    55
    66    output_transaction = True
    77
    8     def handle_app(self, app, **options):
     8    def handle_app(self, apps, **options):
    99        from django.core.management.sql import sql_all
    10         return u'\n'.join(sql_all(app, self.style)).encode('utf-8')
     10        return u'\n'.join(sql_all(apps, self.style)).encode('utf-8')
  • django/core/management/commands/sqlcustom.py

     
    1 from django.core.management.base import AppCommand
     1from django.core.management.base import CrossAppCommand
    22
    3 class Command(AppCommand):
     3class Command(CrossAppCommand):
    44    help = "Prints the custom table modifying SQL statements for the given app name(s)."
    55
    66    output_transaction = True
    77
    8     def handle_app(self, app, **options):
     8    def handle_app(self, apps, **options):
    99        from django.core.management.sql import sql_custom
    10         return u'\n'.join(sql_custom(app, self.style)).encode('utf-8')
     10        return u'\n'.join(sql_custom(apps, self.style)).encode('utf-8')
  • django/core/management/commands/sql.py

     
    1 from django.core.management.base import AppCommand
     1from django.core.management.base import CrossAppCommand
    22
    3 class Command(AppCommand):
     3class Command(CrossAppCommand):
    44    help = "Prints the CREATE TABLE SQL statements for the given app name(s)."
    55
    66    output_transaction = True
    77
    8     def handle_app(self, app, **options):
     8    def handle_app(self, apps, **options):
    99        from django.core.management.sql import sql_create
    10         return u'\n'.join(sql_create(app, self.style)).encode('utf-8')
     10        return u'\n'.join(sql_create(apps, self.style)).encode('utf-8')
  • django/core/management/commands/sqlreset.py

     
    1 from django.core.management.base import AppCommand
     1from django.core.management.base import CrossAppCommand
    22
    3 class Command(AppCommand):
     3class Command(CrossAppCommand):
    44    help = "Prints the DROP TABLE SQL, then the CREATE TABLE SQL, for the given app name(s)."
    55
    66    output_transaction = True
    77
    8     def handle_app(self, app, **options):
     8    def handle_app(self, apps, **options):
    99        from django.core.management.sql import sql_reset
    10         return u'\n'.join(sql_reset(app, self.style)).encode('utf-8')
     10        return u'\n'.join(sql_reset(apps, self.style)).encode('utf-8')
  • django/core/management/commands/sqlclear.py

     
    1 from django.core.management.base import AppCommand
     1from django.core.management.base import CrossAppCommand
    22
    3 class Command(AppCommand):
     3class Command(CrossAppCommand):
    44    help = "Prints the DROP TABLE SQL statements for the given app name(s)."
    55
    66    output_transaction = True
    77
    8     def handle_app(self, app, **options):
     8    def handle_app(self, apps, **options):
    99        from django.core.management.sql import sql_delete
    10         return u'\n'.join(sql_delete(app, self.style)).encode('utf-8')
     10        return u'\n'.join(sql_delete(apps, self.style)).encode('utf-8')
  • django/core/management/commands/sqlindexes.py

     
    1 from django.core.management.base import AppCommand
     1from django.core.management.base import CrossAppCommand
    22
    3 class Command(AppCommand):
     3class Command(CrossAppCommand):
    44    help = "Prints the CREATE INDEX SQL statements for the given model module name(s)."
    55
    66    output_transaction = True
  • django/core/management/commands/reset.py

     
    1 from django.core.management.base import AppCommand, CommandError
     1from django.core.management.base import CrossAppCommand, CommandError
    22from django.core.management.color import no_style
    33from optparse import make_option
    44
    5 class Command(AppCommand):
    6     option_list = AppCommand.option_list + (
     5class Command(CrossAppCommand):
     6    option_list = CrossAppCommand.option_list + (
    77        make_option('--noinput', action='store_false', dest='interactive', default=True,
    88            help='Tells Django to NOT prompt the user for input of any kind.'),
    99    )
     
    1212
    1313    output_transaction = True
    1414
    15     def handle_app(self, app, **options):
     15    def handle_app(self, apps, **options):
    1616        from django.db import connection, transaction
    1717        from django.conf import settings
    1818        from django.core.management.sql import sql_reset
     19       
     20        for app in apps:
     21            app_name = app.__name__.split('.')[-2]
    1922
    20         app_name = app.__name__.split('.')[-2]
    21 
    2223        self.style = no_style()
    2324
    24         sql_list = sql_reset(app, self.style)
     25        sql_list = sql_reset(apps, self.style)
    2526
    2627        if options.get('interactive'):
    2728            confirm = raw_input("""
  • django/core/management/base.py

     
    297297        """
    298298        raise NotImplementedError()
    299299
     300class CrossAppCommand(BaseCommand):
     301    """
     302    Modified version of AppCommand which allows for multiple applications to
     303    see each other models.   
     304    """
     305   
     306    args = '<appname appname ...>'
     307
     308    def handle(self, *app_labels, **options):
     309        from django.db import models
     310        from django.core.management.sql import sql_create
     311        if not app_labels:
     312            raise CommandError('Enter at least one appname.')
     313        try:
     314            app_list = [models.get_app(app_label) for app_label in app_labels]
     315        except (ImproperlyConfigured, ImportError), e:
     316            raise CommandError("%s. Are you sure your INSTALLED_APPS setting is correct?" % e)
     317        return self.handle_app(app_list, **options)
     318
     319    def handle_app(self, apps, **options):   
     320        """
     321        Perform the command's actions for ``apps``, which will be the
     322        Python module corresponding to an application name given on
     323        the command line.
     324        """
     325        raise NotImplementedError()
     326   
    300327class LabelCommand(BaseCommand):
    301328    """
    302329    A management command which takes one or more arbitrary arguments
  • django/core/management/sql.py

     
    77except NameError:
    88    from sets import Set as set   # Python 2.3 fallback
    99
    10 def sql_create(app, style):
     10def sql_create(apps, style):
    1111    "Returns a list of the CREATE TABLE SQL statements for the given app."
    1212    from django.db import connection, models
    1313    from django.conf import settings
     
    2323    # We trim models from the current app so that the sqlreset command does not
    2424    # generate invalid SQL (leaving models out of known_models is harmless, so
    2525    # we can be conservative).
    26     app_models = models.get_models(app, include_auto_created=True)
     26    if isinstance(apps, list):
     27        app_models=[]
     28        for app in apps:
     29             for mod in models.get_models(app, include_auto_created=True):
     30                app_models.append(mod)
     31    else:
     32        app_models = models.get_models(apps, include_auto_created=True)
    2733    final_output = []
    2834    tables = connection.introspection.table_names()
    2935    known_models = set([model for model in connection.introspection.installed_models(tables) if model not in app_models])
     
    5460
    5561    return final_output
    5662
    57 def sql_delete(app, style):
     63def sql_delete(apps, style):
    5864    "Returns a list of the DROP TABLE SQL statements for the given app."
    5965    from django.db import connection, models
    6066    from django.db.backends.util import truncate_name
     
    7682
    7783    # Output DROP TABLE statements for standard application tables.
    7884    to_delete = set()
    79 
     85    if not isinstance(apps, list):
     86        apps=[apps]
    8087    references_to_delete = {}
    81     app_models = models.get_models(app, include_auto_created=True)
    82     for model in app_models:
    83         if cursor and connection.introspection.table_name_converter(model._meta.db_table) in table_names:
    84             # The table exists, so it needs to be dropped
    85             opts = model._meta
    86             for f in opts.local_fields:
    87                 if f.rel and f.rel.to not in to_delete:
    88                     references_to_delete.setdefault(f.rel.to, []).append( (model, f) )
     88    for app in apps:
     89        app_models = models.get_models(app, include_auto_created=True)
     90        for model in app_models:
     91            if cursor and connection.introspection.table_name_converter(model._meta.db_table) in table_names:
     92                # The table exists, so it needs to be dropped
     93                opts = model._meta
     94                for f in opts.local_fields:
     95                    if f.rel and f.rel.to not in to_delete:
     96                        references_to_delete.setdefault(f.rel.to, []).append( (model, f) )
    8997
    90             to_delete.add(model)
     98                to_delete.add(model)
    9199
    92     for model in app_models:
    93         if connection.introspection.table_name_converter(model._meta.db_table) in table_names:
    94             output.extend(connection.creation.sql_destroy_model(model, references_to_delete, style))
     100        for model in app_models:
     101            if connection.introspection.table_name_converter(model._meta.db_table) in table_names:
     102                output.extend(connection.creation.sql_destroy_model(model, references_to_delete, style))
    95103
    96104    # Close database connection explicitly, in case this output is being piped
    97105    # directly into a database client, to avoid locking issues.
     
    120128    statements = connection.ops.sql_flush(style, tables, connection.introspection.sequence_list())
    121129    return statements
    122130
    123 def sql_custom(app, style):
     131def sql_custom(apps, style):
    124132    "Returns a list of the custom table modifying SQL statements for the given app."
    125133    from django.db.models import get_models
    126134    output = []
    127 
    128     app_models = get_models(app)
    129     app_dir = os.path.normpath(os.path.join(os.path.dirname(app.__file__), 'sql'))
    130 
    131     for model in app_models:
    132         output.extend(custom_sql_for_model(model, style))
    133 
     135    app_models = []
     136    if not isinstance(apps, list):
     137        apps=[apps]
     138    for app in apps:
     139        app_dir = os.path.normpath(os.path.join(os.path.dirname(app.__file__), 'sql'))
     140        for model in get_models(app):
     141            output.extend(custom_sql_for_model(model, style))
    134142    return output
    135143
    136 def sql_indexes(app, style):
     144def sql_indexes(apps, style):
    137145    "Returns a list of the CREATE INDEX SQL statements for all models in the given app."
    138146    from django.db import connection, models
    139147    output = []
    140     for model in models.get_models(app):
    141         output.extend(connection.creation.sql_indexes_for_model(model, style))
     148    if not isinstance(apps, list):
     149        apps=[apps]
     150    for app in apps:
     151        for model in models.get_models(app):
     152            output.extend(connection.creation.sql_indexes_for_model(model, style))
    142153    return output
    143154
    144155def sql_all(app, style):
Back to Top