Ticket #12672: t12672-r12278.1.diff

File t12672-r12278.1.diff, 9.1 KB (added by russellm, 6 years ago)

First rough draft at an implementation.

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

    diff -r d205a9ab4b3b django/core/management/commands/loaddata.py
    a b  
    88from django.core import serializers
    99from django.core.management.base import BaseCommand
    1010from django.core.management.color import no_style
    11 from django.db import connections, transaction, DEFAULT_DB_ALIAS
     11from django.db import connections, router, transaction, DEFAULT_DB_ALIAS
    1212from django.db.models import get_apps
    1313from django.utils.itercompat import product
    1414
     
    3131        make_option('--database', action='store', dest='database',
    3232            default=DEFAULT_DB_ALIAS, help='Nominates a specific database to load '
    3333                'fixtures into. Defaults to the "default" database.'),
    34         make_option('-e', '--exclude', dest='exclude',action='append', default=[],
    35             help='App to exclude (use multiple --exclude to exclude multiple apps).'),
    3634    )
    3735
    3836    def handle(self, *fixture_labels, **options):
    3937        using = options.get('database', DEFAULT_DB_ALIAS)
    40         excluded_apps = options.get('exclude', [])
    4138
    4239        connection = connections[using]
    4340        self.style = no_style()
     
    171168                            try:
    172169                                objects = serializers.deserialize(format, fixture, using=using)
    173170                                for obj in objects:
    174                                     if obj.object._meta.app_label not in excluded_apps:
     171                                    if router.allow_syncdb(using, obj.object):
    175172                                        objects_in_fixture += 1
    176173                                        models.add(obj.object.__class__)
    177174                                        obj.save(using=using)
  • django/core/management/commands/syncdb.py

    diff -r d205a9ab4b3b django/core/management/commands/syncdb.py
    a b  
    1616        make_option('--database', action='store', dest='database',
    1717            default=DEFAULT_DB_ALIAS, help='Nominates a database to synchronize. '
    1818                'Defaults to the "default" database.'),
    19         make_option('-e', '--exclude', dest='exclude',action='append', default=[],
    20             help='App to exclude (use multiple --exclude to exclude multiple apps).'),
    2119    )
    2220    help = "Create the database tables for all apps in INSTALLED_APPS whose tables haven't already been created."
    2321
     
    2624        verbosity = int(options.get('verbosity', 1))
    2725        interactive = options.get('interactive')
    2826        show_traceback = options.get('traceback', False)
    29         exclude = options.get('exclude', [])
    3027
    3128        self.style = no_style()
    3229
     
    5956        created_models = set()
    6057        pending_references = {}
    6158
    62         excluded_apps = set(models.get_app(app_label) for app_label in exclude)
    63         included_apps = set(app for app in models.get_apps() if app not in excluded_apps)
    64 
    6559        # Create the tables for each model
    66         for app in included_apps:
     60        for app in models.get_apps():
    6761            app_name = app.__name__.split('.')[-2]
    68             model_list = models.get_models(app, include_auto_created=True)
     62            model_list = models.get_models(app, include_auto_created=True, using=db)
    6963            for model in model_list:
    7064                # Create the model's database table, if it doesn't already exist.
    7165                if verbosity >= 2:
     
    10195
    10296        # Install custom SQL for the app (but only if this
    10397        # is a model we've just created)
    104         for app in included_apps:
     98        for app in models.get_apps():
    10599            app_name = app.__name__.split('.')[-2]
    106100            for model in models.get_models(app):
    107101                if model in created_models:
     
    126120                            print "No custom SQL for %s.%s model" % (app_name, model._meta.object_name)
    127121
    128122        # Install SQL indicies for all newly created models
    129         for app in included_apps:
     123        for app in models.get_apps():
    130124            app_name = app.__name__.split('.')[-2]
    131125            for model in models.get_models(app):
    132126                if model in created_models:
     
    145139                            transaction.commit_unless_managed(using=db)
    146140
    147141        from django.core.management import call_command
    148         call_command('loaddata', 'initial_data', verbosity=verbosity, exclude=exclude, database=db)
     142        call_command('loaddata', 'initial_data', verbosity=verbosity, database=db)
  • django/db/models/loading.py

    diff -r d205a9ab4b3b django/db/models/loading.py
    a b  
    44from django.core.exceptions import ImproperlyConfigured
    55from django.utils.datastructures import SortedDict
    66from django.utils.importlib import import_module
     7from django.db import router
    78
    89import sys
    910import os
     
    132133        self._populate()
    133134        return self.app_errors
    134135
    135     def get_models(self, app_mod=None, include_auto_created=False, include_deferred=False):
     136    def get_models(self, app_mod=None, include_auto_created=False,
     137                   include_deferred=False, using=None):
    136138        """
    137139        Given a module containing models, returns a list of the models.
    138140        Otherwise returns a list of all installed models.
     
    143145
    144146        By default, models created to satisfy deferred attribute
    145147        queries are *not* included in the list of models. However, if
    146         you specify include_deferred, they will be.
     148        you specify include_deferred=True, they will be.
     149
     150        By default, if a model is defined, and matches the other arguments,
     151        it will be returned. However, if a using argument is specified, only
     152        models that are synchronized onto the named database will be returned.
    147153        """
    148         cache_key = (app_mod, include_auto_created, include_deferred)
     154        cache_key = (app_mod, include_auto_created, include_deferred, using)
    149155        try:
    150156            return self._get_models_cache[cache_key]
    151157        except KeyError:
     
    160166            model_list.extend(
    161167                model for model in app.values()
    162168                if ((not model._deferred or include_deferred)
    163                     and (not model._meta.auto_created or include_auto_created))
     169                    and (not model._meta.auto_created or include_auto_created)
     170                    and (using is None or router.allow_syncdb(using, model)))
    164171            )
    165172        self._get_models_cache[cache_key] = model_list
    166173        return model_list
  • django/db/utils.py

    diff -r d205a9ab4b3b django/db/utils.py
    a b  
    120120            if allow is not None:
    121121                return allow
    122122        return obj1._state.db == obj2._state.db
     123
     124    def allow_syncdb(self, db, model):
     125        for router in self.routers:
     126            allow = router.allow_syncdb(db, model)
     127            if allow is not None:
     128                return allow
     129        return True
  • docs/ref/django-admin.txt

    diff -r d205a9ab4b3b docs/ref/django-admin.txt
    a b  
    423423have specified that you want to load data onto the ``master``
    424424database.
    425425
    426 Excluding applications from loading
    427 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    428 
    429 .. versionadded:: 1.2
    430 
    431 The :djadminopt:`--exclude` option may be provided to prevent specific
    432 applications from being loaded.
    433 
    434 For example, if you wanted to exclude models from ``django.contrib.auth``
    435 from being loaded into your database, you would call::
    436 
    437     django-admin.py loaddata mydata.json --exclude auth
    438 
    439 This will look for for a JSON fixture called ``mydata`` in all the
    440 usual locations - including the ``fixtures`` directory of the
    441 ``django.contrib.auth`` application. However, any fixture object that
    442 identifies itself as belonging to the ``auth`` application (e.g.,
    443 instance of ``auth.User``) would be ignored by loaddata.
    444 
    445426makemessages
    446427------------
    447428
  • docs/topics/db/multi-db.txt

    diff -r d205a9ab4b3b docs/topics/db/multi-db.txt
    a b  
    6666    $ ./manage.py syncdb --database=users
    6767
    6868If you don't want every application to be synchronized onto a
    69 particular database. you can specify the :djadminopt:`--exclude`
    70 argument to :djadmin:`syncdb`. The :djadminopt:`--exclude` option lets
    71 you prevent a specific application or applications from being
    72 synchronized. For example, if you don't want the ``sales`` application
    73 to be in the ``users`` database, you could run::
    74 
    75     $ ./manage.py syncdb --database=users --exclude=sales
     69particular database, you can define a :ref:`database
     70router<topics-db-multi-db-routing>` that implements a policy
     71constraining the availability of particular models.
    7672
    7773Alternatively, if you want fine-grained control of synchronization,
    7874you can pipe all or part of the output of :djadmin:`sqlall` for a
Back to Top