1
from django.core.exceptions import ImproperlyConfigured
3
from collections import OrderedDict
4
from optparse import make_option
6
from django.apps import apps
2
7
from django.core.management.base import BaseCommand, CommandError
3
8
from django.core import serializers
4
9
from django.db import router, DEFAULT_DB_ALIAS
5
from django.utils.datastructures import SortedDict
10
from django.utils.deprecation import RemovedInDjango19Warning
7
from optparse import make_option
9
13
class Command(BaseCommand):
10
14
option_list = BaseCommand.option_list + (
13
17
make_option('--indent', default=None, dest='indent', type='int',
14
18
help='Specifies the indent level to use when pretty-printing output'),
15
19
make_option('--database', action='store', dest='database',
16
default=DEFAULT_DB_ALIAS, help='Nominates a specific database to dump '
17
'fixtures from. Defaults to the "default" database.'),
18
make_option('-e', '--exclude', dest='exclude',action='append', default=[],
19
help='An appname or appname.ModelName to exclude (use multiple --exclude to exclude multiple apps/models).'),
20
default=DEFAULT_DB_ALIAS,
21
help='Nominates a specific database to dump fixtures from. '
22
'Defaults to the "default" database.'),
23
make_option('-e', '--exclude', dest='exclude', action='append', default=[],
24
help='An app_label or app_label.ModelName to exclude '
25
'(use multiple --exclude to exclude multiple apps/models).'),
20
26
make_option('-n', '--natural', action='store_true', dest='use_natural_keys', default=False,
21
help='Use natural keys if they are available.'),
27
help='Use natural keys if they are available (deprecated: use --natural-foreign instead).'),
28
make_option('--natural-foreign', action='store_true', dest='use_natural_foreign_keys', default=False,
29
help='Use natural foreign keys if they are available.'),
30
make_option('--natural-primary', action='store_true', dest='use_natural_primary_keys', default=False,
31
help='Use natural primary keys if they are available.'),
22
32
make_option('-a', '--all', action='store_true', dest='use_base_manager', default=False,
23
help="Use Django's base manager to dump all models stored in the database, including those that would otherwise be filtered or modified by a custom manager."),
24
make_option('--pks', dest='primary_keys', help="Only dump objects with "
25
"given primary keys. Accepts a comma seperated list of keys. "
26
"This option will only work when you specify one model."),
33
help="Use Django's base manager to dump all models stored in the database, "
34
"including those that would otherwise be filtered or modified by a custom manager."),
35
make_option('--pks', dest='primary_keys',
36
help="Only dump objects with given primary keys. "
37
"Accepts a comma separated list of keys. "
38
"This option will only work when you specify one model."),
28
40
help = ("Output the contents of the database as a fixture of the given "
29
41
"format (using each model's default manager unless --all is "
31
args = '[appname appname.ModelName ...]'
43
args = '[app_label app_label.ModelName ...]'
33
45
def handle(self, *app_labels, **options):
34
from django.db.models import get_app, get_apps, get_model
36
46
format = options.get('format')
37
47
indent = options.get('indent')
38
48
using = options.get('database')
39
49
excludes = options.get('exclude')
40
50
show_traceback = options.get('traceback')
41
51
use_natural_keys = options.get('use_natural_keys')
53
warnings.warn("``--natural`` is deprecated; use ``--natural-foreign`` instead.",
54
RemovedInDjango19Warning)
55
use_natural_foreign_keys = options.get('use_natural_foreign_keys') or use_natural_keys
56
use_natural_primary_keys = options.get('use_natural_primary_keys')
42
57
use_base_manager = options.get('use_base_manager')
43
58
pks = options.get('primary_keys')
51
66
excluded_models = set()
52
67
for exclude in excludes:
54
app_label, model_name = exclude.split('.', 1)
55
model_obj = get_model(app_label, model_name)
70
model = apps.get_model(exclude)
57
72
raise CommandError('Unknown model in excludes: %s' % exclude)
58
excluded_models.add(model_obj)
73
excluded_models.add(model)
61
app_obj = get_app(exclude)
62
excluded_apps.add(app_obj)
63
except ImproperlyConfigured:
76
app_config = apps.get_app_config(exclude)
64
78
raise CommandError('Unknown app in excludes: %s' % exclude)
79
excluded_apps.add(app_config)
66
81
if len(app_labels) == 0:
68
83
raise CommandError("You can only use --pks option with one model")
69
app_list = SortedDict((app, None) for app in get_apps() if app not in excluded_apps)
84
app_list = OrderedDict((app_config, None)
85
for app_config in apps.get_app_configs()
86
if app_config.models_module is not None and app_config not in excluded_apps)
71
88
if len(app_labels) > 1 and primary_keys:
72
89
raise CommandError("You can only use --pks option with one model")
73
app_list = SortedDict()
90
app_list = OrderedDict()
74
91
for label in app_labels:
76
93
app_label, model_label = label.split('.')
78
app = get_app(app_label)
79
except ImproperlyConfigured:
95
app_config = apps.get_app_config(app_label)
80
97
raise CommandError("Unknown application: %s" % app_label)
81
if app in excluded_apps:
98
if app_config.models_module is None or app_config in excluded_apps:
83
model = get_model(app_label, model_label)
101
model = app_config.get_model(model_label)
85
103
raise CommandError("Unknown model: %s.%s" % (app_label, model_label))
87
if app in app_list.keys():
88
if app_list[app] and model not in app_list[app]:
89
app_list[app].append(model)
91
app_list[app] = [model]
105
app_list_value = app_list.setdefault(app_config, [])
107
# We may have previously seen a "all-models" request for
108
# this app (no model qualifier was given). In this case
109
# there is no need adding specific models to the list.
110
if app_list_value is not None:
111
if model not in app_list_value:
112
app_list_value.append(model)
92
113
except ValueError:
94
115
raise CommandError("You can only use --pks option with one model")
95
116
# This is just an app - no model qualifier
98
app = get_app(app_label)
99
except ImproperlyConfigured:
119
app_config = apps.get_app_config(app_label)
100
121
raise CommandError("Unknown application: %s" % app_label)
101
if app in excluded_apps:
122
if app_config.models_module is None or app_config in excluded_apps:
124
app_list[app_config] = None
105
126
# Check that the serialization format exists; this is a shortcut to
106
127
# avoid collating all the objects and _then_ failing.
133
154
self.stdout.ending = None
134
155
serializers.serialize(format, get_objects(), indent=indent,
135
use_natural_keys=use_natural_keys, stream=self.stdout)
156
use_natural_foreign_keys=use_natural_foreign_keys,
157
use_natural_primary_keys=use_natural_primary_keys,
136
159
except Exception as e:
137
160
if show_traceback:
139
162
raise CommandError("Unable to serialize database: %s" % e)
141
165
def sort_dependencies(app_list):
142
"""Sort a list of app,modellist pairs into a single list of models.
166
"""Sort a list of (app_config, models) pairs into a single list of models.
144
168
The single list of models is sorted so that any model with a natural key
145
169
is serialized before a normal model, and any model with a natural key
146
170
dependency has it's dependencies serialized first.
148
from django.db.models import get_model, get_models
149
172
# Process the list of models, and get the list of dependencies
150
173
model_dependencies = []
152
for app, model_list in app_list:
175
for app_config, model_list in app_list:
153
176
if model_list is None:
154
model_list = get_models(app)
177
model_list = app_config.get_models()
156
179
for model in model_list:
157
180
models.add(model)