def __init__(self, stream_or_string, **options): """ Init this serializer given a stream or a string """ self.options = options if isinstance(stream_or_string, basestring): self.stream = StringIO(stream_or_string) else: self.stream = stream_or_string # hack to make sure that the models have all been loaded before # deserialization starts (otherwise subclass calls to get_model() # and friends might fail...) models.get_apps()
def django_table_names(self, only_existing=False): """ Returns a list of all table names that have associated Django models and are in INSTALLED_APPS. If only_existing is True, the resulting list will only include the tables that actually exist in the database. """ from my_django.db import models, router tables = set() for app in models.get_apps(): for model in models.get_models(app): if not model._meta.managed: continue if not router.allow_syncdb(self.connection.alias, model): continue tables.add(model._meta.db_table) tables.update( [f.m2m_db_table() for f in model._meta.local_many_to_many]) tables = list(tables) if only_existing: existing_tables = self.table_names() tables = [ t for t in tables if self.table_name_converter(t) in existing_tables ] return tables
def sequence_list(self): "Returns a list of information about all DB sequences for all models in all apps." from my_django.db import models, router apps = models.get_apps() sequence_list = [] for app in apps: for model in models.get_models(app): if not model._meta.managed: continue if not router.allow_syncdb(self.connection.alias, model): continue for f in model._meta.local_fields: if isinstance(f, models.AutoField): sequence_list.append({ 'table': model._meta.db_table, 'column': f.column }) break # Only one AutoField is allowed per model, so don't bother continuing. for f in model._meta.local_many_to_many: # If this is an m2m using an intermediate table, # we don't need to reset the sequence. if f.rel.through is None: sequence_list.append({ 'table': f.m2m_db_table(), 'column': None }) return sequence_list
def emit_post_sync_signal(created_models, verbosity, interactive, db): # Emit the post_sync signal for every application. for app in models.get_apps(): app_name = app.__name__.split('.')[-2] if verbosity >= 2: print "Running post-sync handlers for application", app_name models.signals.post_syncdb.send(sender=app, app=app, created_models=created_models, verbosity=verbosity, interactive=interactive, db=db)
def installed_models(self, tables): "Returns a set of all models represented by the provided list of table names." from my_django.db import models, router all_models = [] for app in models.get_apps(): for model in models.get_models(app): if router.allow_syncdb(self.connection.alias, model): all_models.append(model) tables = map(self.table_name_converter, tables) return set([ m for m in all_models if self.table_name_converter(m._meta.db_table) in tables ])
def build_suite(self, test_labels, extra_tests=None, **kwargs): suite = unittest.TestSuite() if test_labels: for label in test_labels: if '.' in label: suite.addTest(build_test(label)) else: app = get_app(label) suite.addTest(build_suite(app)) else: for app in get_apps(): suite.addTest(build_suite(app)) if extra_tests: for test in extra_tests: suite.addTest(test) return reorder_suite(suite, (TestCase,))
def handle(self, *app_labels, **options): from my_django.db.models import get_app, get_apps, get_model format = options.get('format') indent = options.get('indent') using = options.get('database') excludes = options.get('exclude') show_traceback = options.get('traceback') use_natural_keys = options.get('use_natural_keys') use_base_manager = options.get('use_base_manager') excluded_apps = set() excluded_models = set() for exclude in excludes: if '.' in exclude: app_label, model_name = exclude.split('.', 1) model_obj = get_model(app_label, model_name) if not model_obj: raise CommandError('Unknown model in excludes: %s' % exclude) excluded_models.add(model_obj) else: try: app_obj = get_app(exclude) excluded_apps.add(app_obj) except ImproperlyConfigured: raise CommandError('Unknown app in excludes: %s' % exclude) if len(app_labels) == 0: app_list = SortedDict( (app, None) for app in get_apps() if app not in excluded_apps) else: app_list = SortedDict() for label in app_labels: try: app_label, model_label = label.split('.') try: app = get_app(app_label) except ImproperlyConfigured: raise CommandError("Unknown application: %s" % app_label) if app in excluded_apps: continue model = get_model(app_label, model_label) if model is None: raise CommandError("Unknown model: %s.%s" % (app_label, model_label)) if app in app_list.keys(): if app_list[app] and model not in app_list[app]: app_list[app].append(model) else: app_list[app] = [model] except ValueError: # This is just an app - no model qualifier app_label = label try: app = get_app(app_label) except ImproperlyConfigured: raise CommandError("Unknown application: %s" % app_label) if app in excluded_apps: continue app_list[app] = None # Check that the serialization format exists; this is a shortcut to # avoid collating all the objects and _then_ failing. if format not in serializers.get_public_serializer_formats(): raise CommandError("Unknown serialization format: %s" % format) try: serializers.get_serializer(format) except KeyError: raise CommandError("Unknown serialization format: %s" % format) # Now collate the objects to be serialized. objects = [] for model in sort_dependencies(app_list.items()): if model in excluded_models: continue if not model._meta.proxy and router.allow_syncdb(using, model): if use_base_manager: objects.extend(model._base_manager.using(using).all()) else: objects.extend(model._default_manager.using(using).all()) try: return serializers.serialize(format, objects, indent=indent, use_natural_keys=use_natural_keys) except Exception, e: if show_traceback: raise raise CommandError("Unable to serialize database: %s" % e)
def Deserializer(object_list, **options): """ Deserialize simple Python objects back into Django ORM instances. It's expected that you pass the Python objects themselves (instead of a stream or a string) to the constructor """ db = options.pop('using', DEFAULT_DB_ALIAS) models.get_apps() for d in object_list: # Look up the model and starting build a dict of data for it. Model = _get_model(d["model"]) data = {Model._meta.pk.attname: Model._meta.pk.to_python(d["pk"])} m2m_data = {} # Handle each field for (field_name, field_value) in d["fields"].iteritems(): if isinstance(field_value, str): field_value = smart_unicode(field_value, options.get( "encoding", settings.DEFAULT_CHARSET), strings_only=True) field = Model._meta.get_field(field_name) # Handle M2M relations if field.rel and isinstance(field.rel, models.ManyToManyRel): if hasattr(field.rel.to._default_manager, 'get_by_natural_key'): def m2m_convert(value): if hasattr(value, '__iter__'): return field.rel.to._default_manager.db_manager( db).get_by_natural_key(*value).pk else: return smart_unicode( field.rel.to._meta.pk.to_python(value)) else: m2m_convert = lambda v: smart_unicode( field.rel.to._meta.pk.to_python(v)) m2m_data[field.name] = [m2m_convert(pk) for pk in field_value] # Handle FK fields elif field.rel and isinstance(field.rel, models.ManyToOneRel): if field_value is not None: if hasattr(field.rel.to._default_manager, 'get_by_natural_key'): if hasattr(field_value, '__iter__'): obj = field.rel.to._default_manager.db_manager( db).get_by_natural_key(*field_value) value = getattr(obj, field.rel.field_name) # If this is a natural foreign key to an object that # has a FK/O2O as the foreign key, use the FK value if field.rel.to._meta.pk.rel: value = value.pk else: value = field.rel.to._meta.get_field( field.rel.field_name).to_python(field_value) data[field.attname] = value else: data[field.attname] = field.rel.to._meta.get_field( field.rel.field_name).to_python(field_value) else: data[field.attname] = None # Handle all other fields else: data[field.name] = field.to_python(field_value) yield base.DeserializedObject(Model(**data), m2m_data)
def handle_noargs(self, **options): db = options.get('database') connection = connections[db] verbosity = int(options.get('verbosity')) interactive = options.get('interactive') self.style = no_style() # Import the 'management' module within each installed app, to register # dispatcher events. for app_name in settings.INSTALLED_APPS: try: import_module('.management', app_name) except ImportError: pass sql_list = sql_flush(self.style, connection, only_django=True) if interactive: confirm = raw_input("""You have requested a flush of the database. This will IRREVERSIBLY DESTROY all data currently in the %r database, and return each table to the state it was in after syncdb. Are you sure you want to do this? Type 'yes' to continue, or 'no' to cancel: """ % connection.settings_dict['NAME']) else: confirm = 'yes' if confirm == 'yes': try: cursor = connection.cursor() for sql in sql_list: cursor.execute(sql) except Exception, e: transaction.rollback_unless_managed(using=db) raise CommandError( """Database %s couldn't be flushed. Possible reasons: * The database isn't running or isn't configured correctly. * At least one of the expected database tables doesn't exist. * The SQL was invalid. Hint: Look at the output of 'django-admin.py sqlflush'. That's the SQL this command wasn't able to run. The full error: %s""" % (connection.settings_dict['NAME'], e)) transaction.commit_unless_managed(using=db) # Emit the post sync signal. This allows individual # applications to respond as if the database had been # sync'd from scratch. all_models = [] for app in models.get_apps(): all_models.extend([ m for m in models.get_models(app, include_auto_created=True) if router.allow_syncdb(db, m) ]) emit_post_sync_signal(set(all_models), verbosity, interactive, db) # Reinstall the initial_data fixture. kwargs = options.copy() kwargs['database'] = db call_command('loaddata', 'initial_data', **kwargs)
def update_all_contenttypes(verbosity=2, **kwargs): for app in get_apps(): update_contenttypes(app, None, verbosity, **kwargs)
def handle(self, *fixture_labels, **options): using = options.get('database') connection = connections[using] self.style = no_style() if not len(fixture_labels): self.stderr.write( self.style.ERROR("No database fixture specified. Please provide the path of at least one fixture in the command line.\n") ) return verbosity = int(options.get('verbosity')) show_traceback = options.get('traceback') # commit is a stealth option - it isn't really useful as # a command line option, but it can be useful when invoking # loaddata from within another script. # If commit=True, loaddata will use its own transaction; # if commit=False, the data load SQL will become part of # the transaction in place when loaddata was invoked. commit = options.get('commit', True) # Keep a count of the installed objects and fixtures fixture_count = 0 loaded_object_count = 0 fixture_object_count = 0 models = set() humanize = lambda dirname: "'%s'" % dirname if dirname else 'absolute path' # Get a cursor (even though we don't need one yet). This has # the side effect of initializing the test database (if # it isn't already initialized). cursor = connection.cursor() # Start transaction management. All fixtures are installed in a # single transaction to ensure that all references are resolved. if commit: transaction.commit_unless_managed(using=using) transaction.enter_transaction_management(using=using) transaction.managed(True, using=using) class SingleZipReader(zipfile.ZipFile): def __init__(self, *args, **kwargs): zipfile.ZipFile.__init__(self, *args, **kwargs) if settings.DEBUG: assert len(self.namelist()) == 1, "Zip-compressed fixtures must contain only one file." def read(self): return zipfile.ZipFile.read(self, self.namelist()[0]) compression_types = { None: open, 'gz': gzip.GzipFile, 'zip': SingleZipReader } if has_bz2: compression_types['bz2'] = bz2.BZ2File app_module_paths = [] for app in get_apps(): if hasattr(app, '__path__'): # It's a 'models/' subpackage for path in app.__path__: app_module_paths.append(path) else: # It's a models.py module app_module_paths.append(app.__file__) app_fixtures = [os.path.join(os.path.dirname(path), 'fixtures') for path in app_module_paths] try: with connection.constraint_checks_disabled(): for fixture_label in fixture_labels: parts = fixture_label.split('.') if len(parts) > 1 and parts[-1] in compression_types: compression_formats = [parts[-1]] parts = parts[:-1] else: compression_formats = compression_types.keys() if len(parts) == 1: fixture_name = parts[0] formats = serializers.get_public_serializer_formats() else: fixture_name, format = '.'.join(parts[:-1]), parts[-1] if format in serializers.get_public_serializer_formats(): formats = [format] else: formats = [] if formats: if verbosity >= 2: self.stdout.write("Loading '%s' fixtures...\n" % fixture_name) else: self.stderr.write( self.style.ERROR("Problem installing fixture '%s': %s is not a known serialization format.\n" % (fixture_name, format))) if commit: transaction.rollback(using=using) transaction.leave_transaction_management(using=using) return if os.path.isabs(fixture_name): fixture_dirs = [fixture_name] else: fixture_dirs = app_fixtures + list(settings.FIXTURE_DIRS) + [''] for fixture_dir in fixture_dirs: if verbosity >= 2: self.stdout.write("Checking %s for fixtures...\n" % humanize(fixture_dir)) label_found = False for combo in product([using, None], formats, compression_formats): database, format, compression_format = combo file_name = '.'.join( p for p in [ fixture_name, database, format, compression_format ] if p ) if verbosity >= 3: self.stdout.write("Trying %s for %s fixture '%s'...\n" % \ (humanize(fixture_dir), file_name, fixture_name)) full_path = os.path.join(fixture_dir, file_name) open_method = compression_types[compression_format] try: fixture = open_method(full_path, 'r') except IOError: if verbosity >= 2: self.stdout.write("No %s fixture '%s' in %s.\n" % \ (format, fixture_name, humanize(fixture_dir))) else: try: if label_found: self.stderr.write(self.style.ERROR("Multiple fixtures named '%s' in %s. Aborting.\n" % (fixture_name, humanize(fixture_dir)))) if commit: transaction.rollback(using=using) transaction.leave_transaction_management(using=using) return fixture_count += 1 objects_in_fixture = 0 loaded_objects_in_fixture = 0 if verbosity >= 2: self.stdout.write("Installing %s fixture '%s' from %s.\n" % \ (format, fixture_name, humanize(fixture_dir))) objects = serializers.deserialize(format, fixture, using=using) for obj in objects: objects_in_fixture += 1 if router.allow_syncdb(using, obj.object.__class__): loaded_objects_in_fixture += 1 models.add(obj.object.__class__) try: obj.save(using=using) except (DatabaseError, IntegrityError), e: msg = "Could not load %(app_label)s.%(object_name)s(pk=%(pk)s): %(error_msg)s" % { 'app_label': obj.object._meta.app_label, 'object_name': obj.object._meta.object_name, 'pk': obj.object.pk, 'error_msg': e } raise e.__class__, e.__class__(msg), sys.exc_info()[2] loaded_object_count += loaded_objects_in_fixture fixture_object_count += objects_in_fixture label_found = True finally: fixture.close() # If the fixture we loaded contains 0 objects, assume that an # error was encountered during fixture loading. if objects_in_fixture == 0: self.stderr.write( self.style.ERROR("No fixture data found for '%s'. (File format may be invalid.)\n" % (fixture_name))) if commit: transaction.rollback(using=using) transaction.leave_transaction_management(using=using) return # Since we disabled constraint checks, we must manually check for # any invalid keys that might have been added table_names = [model._meta.db_table for model in models] connection.check_constraints(table_names=table_names)
class Command(NoArgsCommand): option_list = NoArgsCommand.option_list + ( make_option( '--noinput', action='store_false', dest='interactive', default=True, help='Tells Django to NOT prompt the user for input of any kind.'), make_option('--database', action='store', dest='database', default=DEFAULT_DB_ALIAS, help='Nominates a database to synchronize. ' 'Defaults to the "default" database.'), ) help = "Create the database tables for all apps in INSTALLED_APPS whose tables haven't already been created." def handle_noargs(self, **options): verbosity = int(options.get('verbosity')) interactive = options.get('interactive') show_traceback = options.get('traceback') # Stealth option -- 'load_initial_data' is used by the testing setup # process to disable initial fixture loading. load_initial_data = options.get('load_initial_data', True) self.style = no_style() # Import the 'management' module within each installed app, to register # dispatcher events. for app_name in settings.INSTALLED_APPS: try: import_module('.management', app_name) except ImportError, exc: # This is slightly hackish. We want to ignore ImportErrors # if the "management" module itself is missing -- but we don't # want to ignore the exception if the management module exists # but raises an ImportError for some reason. The only way we # can do this is to check the text of the exception. Note that # we're a bit broad in how we check the text, because different # Python implementations may not use the same text. # CPython uses the text "No module named management" # PyPy uses "No module named myproject.myapp.management" msg = exc.args[0] if not msg.startswith( 'No module named') or 'management' not in msg: raise db = options.get('database') connection = connections[db] cursor = connection.cursor() # Get a list of already installed *models* so that references work right. tables = connection.introspection.table_names() seen_models = connection.introspection.installed_models(tables) created_models = set() pending_references = {} # Build the manifest of apps and models that are to be synchronized all_models = [(app.__name__.split('.')[-2], [ m for m in models.get_models(app, include_auto_created=True) if router.allow_syncdb(db, m) ]) for app in models.get_apps()] def model_installed(model): opts = model._meta converter = connection.introspection.table_name_converter return not ((converter(opts.db_table) in tables) or (opts.auto_created and converter( opts.auto_created._meta.db_table) in tables)) manifest = SortedDict((app_name, filter(model_installed, model_list)) for app_name, model_list in all_models) # Create the tables for each model if verbosity >= 1: print "Creating tables ..." for app_name, model_list in manifest.items(): for model in model_list: # Create the model's database table, if it doesn't already exist. if verbosity >= 3: print "Processing %s.%s model" % (app_name, model._meta.object_name) sql, references = connection.creation.sql_create_model( model, self.style, seen_models) seen_models.add(model) created_models.add(model) for refto, refs in references.items(): pending_references.setdefault(refto, []).extend(refs) if refto in seen_models: sql.extend( connection.creation.sql_for_pending_references( refto, self.style, pending_references)) sql.extend( connection.creation.sql_for_pending_references( model, self.style, pending_references)) if verbosity >= 1 and sql: print "Creating table %s" % model._meta.db_table for statement in sql: cursor.execute(statement) tables.append( connection.introspection.table_name_converter( model._meta.db_table)) transaction.commit_unless_managed(using=db) # Send the post_syncdb signal, so individual apps can do whatever they need # to do at this point. emit_post_sync_signal(created_models, verbosity, interactive, db) # The connection may have been closed by a syncdb handler. cursor = connection.cursor() # Install custom SQL for the app (but only if this # is a model we've just created) if verbosity >= 1: print "Installing custom SQL ..." for app_name, model_list in manifest.items(): for model in model_list: if model in created_models: custom_sql = custom_sql_for_model(model, self.style, connection) if custom_sql: if verbosity >= 2: print "Installing custom SQL for %s.%s model" % ( app_name, model._meta.object_name) try: for sql in custom_sql: cursor.execute(sql) except Exception, e: sys.stderr.write("Failed to install custom SQL for %s.%s model: %s\n" % \ (app_name, model._meta.object_name, e)) if show_traceback: traceback.print_exc() transaction.rollback_unless_managed(using=db) else: transaction.commit_unless_managed(using=db) else: if verbosity >= 3: print "No custom SQL for %s.%s model" % ( app_name, model._meta.object_name)