~ubuntu-branches/ubuntu/quantal/python-django/quantal

« back to all changes in this revision

Viewing changes to django/core/management/commands/loaddata.py

  • Committer: Bazaar Package Importer
  • Author(s): Scott James Remnant, Eddy Mulyono
  • Date: 2008-09-16 12:18:47 UTC
  • mfrom: (1.1.5 upstream) (4.1.1 lenny)
  • Revision ID: james.westby@ubuntu.com-20080916121847-mg225rg5mnsdqzr0
Tags: 1.0-1ubuntu1
* Merge from Debian (LP: #264191), remaining changes:
  - Run test suite on build.

[Eddy Mulyono]
* Update patch to workaround network test case failures.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
from django.core.management.base import BaseCommand
 
2
from django.core.management.color import no_style
 
3
from optparse import make_option
 
4
import sys
 
5
import os
 
6
 
 
7
try:
 
8
    set
 
9
except NameError:
 
10
    from sets import Set as set   # Python 2.3 fallback
 
11
 
 
12
class Command(BaseCommand):
 
13
    option_list = BaseCommand.option_list + (
 
14
        make_option('--verbosity', action='store', dest='verbosity', default='1',
 
15
            type='choice', choices=['0', '1', '2'],
 
16
            help='Verbosity level; 0=minimal output, 1=normal output, 2=all output'),
 
17
    )
 
18
    help = 'Installs the named fixture(s) in the database.'
 
19
    args = "fixture [fixture ...]"
 
20
 
 
21
    def handle(self, *fixture_labels, **options):
 
22
        from django.db.models import get_apps
 
23
        from django.core import serializers
 
24
        from django.db import connection, transaction
 
25
        from django.conf import settings
 
26
 
 
27
        self.style = no_style()
 
28
 
 
29
        verbosity = int(options.get('verbosity', 1))
 
30
        show_traceback = options.get('traceback', False)
 
31
        
 
32
        # commit is a stealth option - it isn't really useful as 
 
33
        # a command line option, but it can be useful when invoking
 
34
        # loaddata from within another script. 
 
35
        # If commit=True, loaddata will use its own transaction;
 
36
        # if commit=False, the data load SQL will become part of
 
37
        # the transaction in place when loaddata was invoked.
 
38
        commit = options.get('commit', True)
 
39
        
 
40
        # Keep a count of the installed objects and fixtures
 
41
        fixture_count = 0
 
42
        object_count = 0
 
43
        objects_per_fixture = []
 
44
        models = set()
 
45
 
 
46
        humanize = lambda dirname: dirname and "'%s'" % dirname or 'absolute path'
 
47
 
 
48
        # Get a cursor (even though we don't need one yet). This has
 
49
        # the side effect of initializing the test database (if
 
50
        # it isn't already initialized).
 
51
        cursor = connection.cursor()
 
52
 
 
53
        # Start transaction management. All fixtures are installed in a
 
54
        # single transaction to ensure that all references are resolved.
 
55
        if commit:
 
56
            transaction.commit_unless_managed()
 
57
            transaction.enter_transaction_management()
 
58
            transaction.managed(True)
 
59
 
 
60
        app_fixtures = [os.path.join(os.path.dirname(app.__file__), 'fixtures') for app in get_apps()]
 
61
        for fixture_label in fixture_labels:
 
62
            parts = fixture_label.split('.')
 
63
            if len(parts) == 1:
 
64
                fixture_name = fixture_label
 
65
                formats = serializers.get_public_serializer_formats()
 
66
            else:
 
67
                fixture_name, format = '.'.join(parts[:-1]), parts[-1]
 
68
                if format in serializers.get_public_serializer_formats():
 
69
                    formats = [format]
 
70
                else:
 
71
                    formats = []
 
72
 
 
73
            if formats:
 
74
                if verbosity > 1:
 
75
                    print "Loading '%s' fixtures..." % fixture_name
 
76
            else:
 
77
                sys.stderr.write(
 
78
                    self.style.ERROR("Problem installing fixture '%s': %s is not a known serialization format." %
 
79
                        (fixture_name, format)))
 
80
                transaction.rollback()
 
81
                transaction.leave_transaction_management()
 
82
                return
 
83
 
 
84
            if os.path.isabs(fixture_name):
 
85
                fixture_dirs = [fixture_name]
 
86
            else:
 
87
                fixture_dirs = app_fixtures + list(settings.FIXTURE_DIRS) + ['']
 
88
 
 
89
            for fixture_dir in fixture_dirs:
 
90
                if verbosity > 1:
 
91
                    print "Checking %s for fixtures..." % humanize(fixture_dir)
 
92
 
 
93
                label_found = False
 
94
                for format in formats:
 
95
                    serializer = serializers.get_serializer(format)
 
96
                    if verbosity > 1:
 
97
                        print "Trying %s for %s fixture '%s'..." % \
 
98
                            (humanize(fixture_dir), format, fixture_name)
 
99
                    try:
 
100
                        full_path = os.path.join(fixture_dir, '.'.join([fixture_name, format]))
 
101
                        fixture = open(full_path, 'r')
 
102
                        if label_found:
 
103
                            fixture.close()
 
104
                            print self.style.ERROR("Multiple fixtures named '%s' in %s. Aborting." %
 
105
                                (fixture_name, humanize(fixture_dir)))
 
106
                            transaction.rollback()
 
107
                            transaction.leave_transaction_management()
 
108
                            return
 
109
                        else:
 
110
                            fixture_count += 1
 
111
                            objects_per_fixture.append(0)
 
112
                            if verbosity > 0:
 
113
                                print "Installing %s fixture '%s' from %s." % \
 
114
                                    (format, fixture_name, humanize(fixture_dir))
 
115
                            try:
 
116
                                objects = serializers.deserialize(format, fixture)
 
117
                                for obj in objects:
 
118
                                    object_count += 1
 
119
                                    objects_per_fixture[-1] += 1
 
120
                                    models.add(obj.object.__class__)
 
121
                                    obj.save()
 
122
                                label_found = True
 
123
                            except (SystemExit, KeyboardInterrupt):
 
124
                                raise
 
125
                            except Exception:
 
126
                                import traceback
 
127
                                fixture.close()
 
128
                                transaction.rollback()
 
129
                                transaction.leave_transaction_management()
 
130
                                if show_traceback:
 
131
                                    import traceback
 
132
                                    traceback.print_exc()
 
133
                                else:
 
134
                                    sys.stderr.write(
 
135
                                        self.style.ERROR("Problem installing fixture '%s': %s\n" %
 
136
                                             (full_path, traceback.format_exc())))
 
137
                                return
 
138
                            fixture.close()
 
139
                    except:
 
140
                        if verbosity > 1:
 
141
                            print "No %s fixture '%s' in %s." % \
 
142
                                (format, fixture_name, humanize(fixture_dir))
 
143
 
 
144
 
 
145
        # If any of the fixtures we loaded contain 0 objects, assume that an
 
146
        # error was encountered during fixture loading.
 
147
        if 0 in objects_per_fixture:
 
148
            sys.stderr.write(
 
149
                self.style.ERROR("No fixture data found for '%s'. (File format may be invalid.)" %
 
150
                    (fixture_name)))
 
151
            transaction.rollback()
 
152
            transaction.leave_transaction_management()
 
153
            return
 
154
            
 
155
        # If we found even one object in a fixture, we need to reset the
 
156
        # database sequences.
 
157
        if object_count > 0:
 
158
            sequence_sql = connection.ops.sequence_reset_sql(self.style, models)
 
159
            if sequence_sql:
 
160
                if verbosity > 1:
 
161
                    print "Resetting sequences"
 
162
                for line in sequence_sql:
 
163
                    cursor.execute(line)
 
164
        
 
165
        if commit:
 
166
            transaction.commit()
 
167
            transaction.leave_transaction_management()
 
168
 
 
169
        if object_count == 0:
 
170
            if verbosity > 1:
 
171
                print "No fixtures found."
 
172
        else:
 
173
            if verbosity > 0:
 
174
                print "Installed %d object(s) from %d fixture(s)" % (object_count, fixture_count)
 
175
                
 
176
        # Close the DB connection. This is required as a workaround for an
 
177
        # edge case in MySQL: if the same connection is used to
 
178
        # create tables, load data, and query, the query can return
 
179
        # incorrect results. See Django #7572, MySQL #37735.
 
180
        if commit:
 
181
            connection.close()