def handle(self, *app_labels, **options): format = options.get('format', 'json') indent = options.get('indent', None) exclude = options.get('exclude', []) show_traceback = options.get('traceback', False) excluded_apps = [apps.get_app(app_label) for app_label in exclude] if len(app_labels) == 0: app_list = [ app for app in apps.get_apps() if app not in excluded_apps ] else: app_list = [apps.get_app(app_label) for app_label in app_labels] # Check that the serialization format exists; this is a shortcut to # avoid collating all the objects and _then_ failing. try: serializers.get_serializer(format) except KeyError: raise CommandError("Unknown serialization format: %s" % format) objects = [] collected = set() for app in app_list: # Yey for ghetto recusion objects, collected = _relational_dumpdata(app, collected) # ****End New stuff try: return serializers.serialize(format, objects, indent=indent) except Exception as e: if show_traceback: raise raise CommandError("Unable to serialize database: %s" % e)
def handle(self, *app_labels, **options): # Activate project's default language translation.activate(settings.LANGUAGE_CODE) comment = options["comment"] batch_size = options["batch_size"] database = options.get('database') verbosity = int(options.get("verbosity", 1)) app_list = OrderedDict() # if no apps given, use all installed. if len(app_labels) == 0: for app in get_apps(): if not app in app_list: app_list[app] = [] for model_class in get_models(app): if not model_class in app_list[app]: app_list[app].append(model_class) else: 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) model_class = get_model(app_label, model_label) if model_class is None: raise CommandError("Unknown model: %s.%s" % (app_label, model_label)) if app in app_list: if app_list[app] and model_class not in app_list[app]: app_list[app].append(model_class) else: app_list[app] = [model_class] except ValueError: # This is just an app - no model qualifier. app_label = label try: app = get_app(app_label) if not app in app_list: app_list[app] = [] for model_class in get_models(app): if not model_class in app_list[app]: app_list[app].append(model_class) except ImproperlyConfigured: raise CommandError("Unknown application: %s" % app_label) # Create revisions. for app, model_classes in app_list.items(): for model_class in model_classes: self.create_initial_revisions(app, model_class, comment, batch_size, verbosity, database=database) # Go back to default language translation.deactivate()
def custom_sql_for_model(model, style, connection): opts = model._meta app_dir = os.path.normpath(os.path.join(os.path.dirname(apps.get_app(model._meta.app_label).__file__), 'sql')) output = [] # Post-creation SQL should come before any initial SQL data is loaded. # However, this should not be done for models that are unmanaged or # for fields that are part of a parent model (via model inheritance). if opts.managed: post_sql_fields = [f for f in opts.local_fields if hasattr(f, 'post_create_sql')] for f in post_sql_fields: output.extend(f.post_create_sql(style, model._meta.db_table)) # Some backends can't execute more than one SQL statement at a time, # so split into separate statements. statements = re.compile(r";[ \t]*$", re.M) # Find custom SQL, if it's available. backend_name = connection.settings_dict['ENGINE'].split('.')[-1] sql_files = [os.path.join(app_dir, "%s.%s.sql" % (opts.object_name.lower(), backend_name)), os.path.join(app_dir, "%s.sql" % opts.object_name.lower())] for sql_file in sql_files: if os.path.exists(sql_file): fp = open(sql_file, 'U') for statement in statements.split(fp.read().decode(settings.FILE_CHARSET)): # Remove any comments from the file statement = re.sub(ur"--.*([\n\Z]|$)", "", statement) if statement.strip(): output.append(statement + u";") fp.close() return output
def handle(self, *args, **options): if options['all']: models = apps.get_models() feedback = "All instances from all models saved." elif options['app']: apps_list = options['app'].split() try: models_list = [] for name in apps_list: models_list.append(apps.get_models(apps.get_app(name))) except ImproperlyConfigured: return self.stdout.write("Can't find '%s' app." % ', '.join(apps_list)) else: models = [item for sublist in models_list for item in sublist] feedback = 'All instances from all models in "%s" saved.' % ', '.join(apps_list) else: try: models = [] for model in args: models.append(apps.get_model(model)) except LookupError: return self.stdout.write("Can't find '%s' model." % args) else: feedback = 'All instances saved.' self.save_objects(models) return self.stdout.write(feedback)
def handle(self, *args, **kwargs): app = apps.get_app('contributions') if not app: return for model in apps.get_models(app): if issubclass(model, Indexable): for instance in model.objects.all(): instance.index()
def stats(request): app = apps.get_app("birthdays") sources = [ model for model in apps.get_models(app) if issubclass(model, PersonSource) ][2:] # first two are base classes not actual sources stats = [ ("Master records total", Person.objects.count()), ("Extended records total", Person.objects.annotate(num_sources=Count("sources")).filter(num_sources__gt=1).count()), ("Number of sources", len(sources) - 3), # there are 3 test sources ("Source records total", PersonSource.objects.count()), ("Sourcing records total", PersonSource.objects.filter(master__isnull=False).count()), ] return render_to_response("stats.html", {"stats": stats}, RequestContext(request))
def handle(self, *args, **options): from django.apps import apps # TODO : Check export mode db.reset_queries() sourceDatabase = options.get('sourceDatabase') dataLimit = options.get('dataLimit') app = apps.get_app(options.get('app')) con = connections[sourceDatabase] if con.vendor != 'oracle': print "Source database has to be oracle." return user = settings.DATABASES[sourceDatabase]['USER'] passwd = settings.DATABASES[sourceDatabase]['PASSWORD'] host = settings.DATABASES[sourceDatabase]['HOST'] port = settings.DATABASES[sourceDatabase]['PORT'] name = settings.DATABASES[sourceDatabase]['NAME'] app_list = OrderedDict((app, None) for app in [app]) tables = [] sorted = sort_dependencies(app_list.items()) lastObjectName = sorted[-1].__name__ filename = lastObjectName + ".postgresql_psycopg2.sql" chemblSQLPath = os.path.join(os.path.dirname(app.__file__),'sql', filename) location = chemblSQLPath oracleHome = os.environ['ORACLE_HOME'] if options.get('dumpfile'): if not options.get('dumpfile').endswith('.sql'): location = os.path.join(options.get('dumpfile'), filename) else: location = options.get('dumpfile') for model in reversed(sorted): if not model._meta.managed: continue tables.append(model._meta.db_table) print self.confTemplate % (oracleHome, host, name, port, user, passwd, user, " ".join(tables), dataLimit, location) if location != chemblSQLPath: print "different! location = " + location + ", chemblSQLPath = " + chemblSQLPath f = open(location, 'w') f.close() os.symlink(location, chemblSQLPath)
def handle(self, *args, **options): fields_data = [] if len(args) != 0: for arg in args: field_spec = arg.split('.') if len(field_spec) == 1: if NEW_META_API: app = apps.get_app(field_spec[0]) models = apps.get_models(app) else: app = get_app(field_spec[0]) models = get_models(app) for model in models: fields_data += all_fsm_fields_data(model) elif len(field_spec) == 2: if NEW_META_API: model = apps.get_model(field_spec[0], field_spec[1]) else: model = get_model(field_spec[0], field_spec[1]) fields_data += all_fsm_fields_data(model) elif len(field_spec) == 3: if NEW_META_API: model = apps.get_model(field_spec[0], field_spec[1]) fields_data.append((model._meta.get_field(field_spec[2])[0], model)) else: model = get_model(field_spec[0], field_spec[1]) fields_data.append((model._meta.get_field_by_name(field_spec[2])[0], model)) else: if NEW_META_API: for model in apps.get_models(): fields_data += all_fsm_fields_data(model) else: for app in get_apps(): for model in get_models(app): fields_data += all_fsm_fields_data(model) if not options['plantuml']: dotdata = generate_dot(fields_data) if options['outputfile']: self.render_output(dotdata, **options) else: print(dotdata) else: plantumldata = generate_plantuml(fields_data) print(plantumldata)
def handle(self, *args, **options): fields_data = [] if len(args) != 0: for arg in args: field_spec = arg.split('.') if len(field_spec) == 1: if NEW_META_API: app = apps.get_app(field_spec[0]) models = apps.get_models(app) else: app = get_app(field_spec[0]) models = get_models(app) for model in models: fields_data += all_fsm_fields_data(model) elif len(field_spec) == 2: if NEW_META_API: model = apps.get_model(field_spec[0], field_spec[1]) else: model = get_model(field_spec[0], field_spec[1]) fields_data += all_fsm_fields_data(model) elif len(field_spec) == 3: if NEW_META_API: model = apps.get_model(field_spec[0], field_spec[1]) fields_data.append( (model._meta.get_field(field_spec[2])[0], model)) else: model = get_model(field_spec[0], field_spec[1]) fields_data.append( (model._meta.get_field_by_name(field_spec[2])[0], model)) else: if NEW_META_API: for model in apps.get_models(): fields_data += all_fsm_fields_data(model) else: for app in get_apps(): for model in get_models(app): fields_data += all_fsm_fields_data(model) dotdata = generate_dot(fields_data) if options['outputfile']: self.render_output(dotdata, **options) else: print(dotdata)
def stats(request): app = apps.get_app("birthdays") sources = [ model for model in apps.get_models(app) if issubclass(model, PersonSource) ][2:] # first two are base classes not actual sources stats = [ ("Master records total", Person.objects.count()), ("Extended records total", Person.objects.annotate(num_sources=Count("sources")).filter( num_sources__gt=1).count()), ("Number of sources", len(sources) - 3), # there are 3 test sources ("Source records total", PersonSource.objects.count()), ("Sourcing records total", PersonSource.objects.filter(master__isnull=False).count()), ] return render_to_response("stats.html", {"stats": stats}, RequestContext(request))
def get_view_names(seo_views): output = [] for name in seo_views: try: app = apps.get_app(name) except: output.append(name) else: app_name = app.__name__.split(".")[:-1] app_name.append("urls") try: urls = __import__(".".join(app_name)).urls except (ImportError, AttributeError): output.append(name) else: for url in urls.urlpatterns: if url.name: output.append(url.name) return output
def build_suite(self, test_labels, extra_tests=None, **kwargs): from django.apps import apps from django.test.runner import reorder_suite suite = self.test_suite() if test_labels: apps_to_test = [apps.get_app(label) for label in test_labels] else: apps_to_test = apps.get_apps() # always get all features for given apps (for convenience) for app in apps_to_test: # Check to see if a separate 'features' module exists, # parallel to the models module features_dir = get_features(app) if features_dir is not None: # build a test suite for this directory suite.addTest(self.make_bdd_test_suite(features_dir)) return reorder_suite(suite, self.reorder_by)
def run_tests(test_labels, verbosity=1, interactive=True, extra_tests=[]): """ worsk exactly as per normal test but only creates the test_db if it doesn't yet exist and does not destroy it when done tables are flushed and fixtures loaded between tests as per usual but if your schema has not changed then this saves significant amounts of time and speeds up the test cycle Run the unit tests for all the test labels in the provided list. Labels must be of the form: - app.TestClass.test_method Run a single specific test method - app.TestClass Run all the test methods in a given class - app Search for doctests and unittests in the named application. When looking for tests, the test runner will look in the models and tests modules for the application. A list of 'extra' tests may also be provided; these tests will be added to the test suite. Returns the number of tests that failed. """ setup_test_environment() settings.DEBUG = False suite = unittest.TestSuite() if test_labels: for label in test_labels: if '.' in label: suite.addTest(build_test(label)) else: app = apps.get_app(label) suite.addTest(build_suite(app)) else: for app in apps.get_apps(): suite.addTest(build_suite(app)) for test in extra_tests: suite.addTest(test) suite = reorder_suite(suite, (TestCase, )) old_name = settings.DATABASES['default']['NAME'] # Everything up to here is from django.test.simple from django.db.backends import creation from django.db import connection, DatabaseError if settings.DATABASES['default']['TEST_NAME']: settings.DATABASES['default']['NAME'] = settings.DATABASES['default'][ 'TEST_NAME'] else: settings.DATABASES['default'][ 'NAME'] = creation.TEST_DATABASE_PREFIX + settings.DATABASES[ 'default']['NAME'] connection.settings_dict["DATABASE_NAME"] = settings.DATABASES['default'][ 'NAME'] # does test db exist already ? try: if settings.DATABASES['default']['ENGINE'] == 'sqlite3': if not os.path.exists(settings.DATABASES['default']['NAME']): raise DatabaseError cursor = connection.cursor() except Exception: # db does not exist # juggling ! create_test_db switches the DATABASE_NAME to the TEST_DATABASE_NAME settings.DATABASES['default']['NAME'] = old_name connection.settings_dict["DATABASE_NAME"] = old_name connection.creation.create_test_db(verbosity, autoclobber=True) else: connection.close() settings.DATABASES['default'][ 'SUPPORTS_TRANSACTIONS'] = connections_support_transactions() result = unittest.TextTestRunner(verbosity=verbosity).run(suite) # Since we don't call destory_test_db, we need to set the db name back. settings.DATABASES['default']['NAME'] = old_name connection.settings_dict["DATABASE_NAME"] = old_name teardown_test_environment() return len(result.failures) + len(result.errors)
def handle(self, *args, **options): apps = [] if options['all_applications']: if get_version() >= 1.9: apps = applications.get_models() else: apps = models.get_apps() for app_label in args: if get_version() >= 1.9: app = applications.get_app(app_label) else: app = models.get_app(app_label) if app not in apps: apps.append(app) self.verbose_names = options['verbose_names'] self.exclude_models = parse_file_or_list(options['exclude_models']) self.exclude_fields = parse_file_or_list(options['exclude_columns']) self.inheritance = options['inheritance'] self.sort_fields = options['sort_fields'] self.bezier = options['bezier'] ET.register_namespace('dia', 'http://www.lysator.liu.se/~alla/dia/') ns = {'dia': 'http://www.lysator.liu.se/~alla/dia/'} dom = ET.fromstring(render_to_string('django-dia/empty.xml', {})) self.layer = dom.find('dia:layer', namespaces=ns) app_colors = {} obj_num = 0 obj_ref = [] model_list = self.get_full_model_list(apps) for model in model_list: mdata = { 'id': obj_num, 'pos': (random.random() * 80, random.random() * 80), 'name': self.get_model_name(model), 'fields': self.get_model_fields(model), 'color': get_model_color(app_colors, model), 'port_idx': 0, } self.xml_make_table(mdata) obj_ref.append((obj_num, model, mdata)) obj_num += 1 for model in model_list: for rel in self.get_model_relations(model): self.prepare_relation_stage2(obj_ref, rel, obj_num) self.xml_make_relation(rel) obj_num += 1 if self.inheritance: for rel in self.get_model_inheritance(model): try: self.prepare_relation_stage2(obj_ref, rel, obj_num) self.xml_make_relation(rel) except ModelNotFoundException: pass xml = six.b('<?xml version="1.0" encoding="UTF-8"?>') + \ ET.tostring(dom, encoding='utf-8') outfile = options['outputfile'] if outfile: if outfile[-4:] != '.dia': outfile += '.dia' with gzip.open(outfile, 'wb') as f: f.write(xml) else: print(xml.decode('utf-8'))
def is_app_installed(self): try: return apps.get_app(self.app_label) except ImproperlyConfigured: return False
def get_all_models(app): try: app_mod = apps.load_app(app) # First try full path except ImportError: app_mod = apps.get_app(app) # Then try just app_label return apps.get_models(app_mod)
def generate_dot(app_labels, **kwargs): disable_fields = kwargs.get('disable_fields', False) include_models = parse_file_or_list(kwargs.get('include_models', "")) all_applications = kwargs.get('all_applications', False) use_subgraph = kwargs.get('group_models', False) verbose_names = kwargs.get('verbose_names', False) inheritance = kwargs.get('inheritance', False) language = kwargs.get('language', None) if language is not None: activate_language(language) exclude_columns = parse_file_or_list(kwargs.get('exclude_columns', "")) exclude_models = parse_file_or_list(kwargs.get('exclude_models', "")) def skip_field(field): if exclude_columns: if verbose_names and field.verbose_name: if field.verbose_name in exclude_columns: return True if field.name in exclude_columns: return True return False t = loader.get_template_from_string(""" digraph name { fontname = "Helvetica" fontsize = 8 node [ fontname = "Helvetica" fontsize = 8 shape = "plaintext" ] edge [ fontname = "Helvetica" fontsize = 8 ] """) c = Context({}) dot = t.render(c) apps = [] if all_applications: apps = djApps.get_apps() for app_label in app_labels: app = djApps.get_app(app_label) if app not in apps: apps.append(app) graphs = [] for app in apps: graph = Context({ 'name': '"%s"' % app.__name__, 'app_name': "%s" % '.'.join(app.__name__.split('.')[:-1]), 'cluster_app_name': "cluster_%s" % app.__name__.replace(".", "_"), 'disable_fields': disable_fields, 'use_subgraph': use_subgraph, 'models': [] }) appmodels = djApps.get_models(app) abstract_models = [] for appmodel in appmodels: abstract_models = abstract_models + \ [abstract_model for abstract_model in appmodel.__bases__ if hasattr( abstract_model, '_meta') and abstract_model._meta.abstract] abstract_models = list(set(abstract_models)) # remove duplicates appmodels = abstract_models + appmodels for appmodel in appmodels: appmodel_abstracts = [abstract_model.__name__ for abstract_model in appmodel.__bases__ if hasattr( abstract_model, '_meta') and abstract_model._meta.abstract] # collect all attribs of abstract superclasses def getBasesAbstractFields(c): _abstract_fields = [] for e in c.__bases__: if hasattr(e, '_meta') and e._meta.abstract: _abstract_fields.extend(e._meta.fields) _abstract_fields.extend(getBasesAbstractFields(e)) return _abstract_fields abstract_fields = getBasesAbstractFields(appmodel) model = { 'app_name': appmodel.__module__.replace(".", "_"), 'name': appmodel.__name__, 'abstracts': appmodel_abstracts, 'fields': [], 'relations': [] } # consider given model name ? def consider(model_name): if exclude_models and model_name in exclude_models: return False return not include_models or model_name in include_models if not consider(appmodel._meta.object_name): continue if verbose_names and appmodel._meta.verbose_name: model['label'] = appmodel._meta.verbose_name else: model['label'] = model['name'] # model attributes def add_attributes(field): if verbose_names and field.verbose_name: label = field.verbose_name else: label = field.name t = type(field).__name__ if isinstance(field, (OneToOneField, ForeignKey)): t += " ({0})".format(field.rel.field_name) # TODO: ManyToManyField, GenericRelation model['fields'].append({ 'name': field.name, 'label': label, 'type': t, 'blank': field.blank, 'abstract': field in abstract_fields, }) # Find all the real attributes. Relations are depicted as graph # edges instead of attributes attributes = [ field for field in appmodel._meta.local_fields if not isinstance(field, RelatedField)] # find primary key and print it first, ignoring implicit id if # other pk exists pk = appmodel._meta.pk if not appmodel._meta.abstract and pk in attributes: add_attributes(pk) for field in attributes: if skip_field(field): continue if not field.primary_key: add_attributes(field) # FIXME: actually many_to_many fields aren't saved in this model's db table, so why should we add an attribute-line for them in the resulting graph? # if appmodel._meta.many_to_many: # for field in appmodel._meta.many_to_many: # if skip_field(field): # continue # add_attributes(field) # relations def add_relation(field, extras=""): if verbose_names and field.verbose_name: label = field.verbose_name else: label = field.name # show related field name if hasattr(field, 'related_query_name'): label += ' (%s)' % field.related_query_name() # handle self-relationships if field.rel.to == 'self': target_model = field.model else: target_model = field.rel.to _rel = { 'target_app': target_model.__module__.replace('.', '_'), 'target': target_model.__name__, 'type': type(field).__name__, 'name': field.name, 'label': label, 'arrows': extras, 'needs_node': True } if _rel not in model['relations'] and consider(_rel['target']): model['relations'].append(_rel) for field in appmodel._meta.local_fields: # excluding field redundant with inheritance relation if field.attname.endswith('_ptr_id'): continue # excluding fields inherited from abstract classes. they too # show as local_fields if field in abstract_fields: continue if skip_field(field): continue if isinstance(field, OneToOneField): add_relation(field, '[arrowhead=none, arrowtail=none]') elif isinstance(field, ForeignKey): add_relation(field, '[arrowhead=none, arrowtail=dot]') for field in appmodel._meta.local_many_to_many: if skip_field(field): continue if isinstance(field, ManyToManyField): if (getattr(field, 'creates_table', False) or # django 1.1. (hasattr(field.rel.through, '_meta') and field.rel.through._meta.auto_created)): # django 1.2 add_relation( field, '[arrowhead=dot arrowtail=dot, dir=both]') elif isinstance(field, GenericRelation): add_relation( field, mark_safe('[style="dotted", arrowhead=normal, arrowtail=normal, dir=both]')) if inheritance: # add inheritance arrows for parent in appmodel.__bases__: if hasattr(parent, "_meta"): # parent is a model l = "multi-table" if parent._meta.abstract: l = "abstract" if appmodel._meta.proxy: l = "proxy" l += r"\ninheritance" _rel = { 'target_app': parent.__module__.replace(".", "_"), 'target': parent.__name__, 'type': "inheritance", 'name': "inheritance", 'label': l, 'arrows': '[arrowhead=empty, arrowtail=none]', 'needs_node': True } # TODO: seems as if abstract models aren't part of # models.getModels, which is why they are printed by # this without any attributes. if _rel not in model['relations'] and consider(_rel['target']): model['relations'].append(_rel) graph['models'].append(model) graphs.append(graph) nodes = [] for graph in graphs: nodes.extend([e['name'] for e in graph['models']]) for graph in graphs: # don't draw duplication nodes because of relations for model in graph['models']: for relation in model['relations']: if relation['target'] in nodes: relation['needs_node'] = False # render templates t = loader.get_template_from_string("""{% if use_subgraph %} subgraph {{ cluster_app_name }} { label=< <TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0"> <TR><TD COLSPAN="2" CELLPADDING="4" ALIGN="CENTER" ><FONT FACE="Helvetica Bold" COLOR="Black" POINT-SIZE="12" >{{ app_name }}</FONT></TD></TR> </TABLE> > color=olivedrab4 style="rounded" {% endif %} {% for model in models %} {{ model.app_name }}_{{ model.name }} [label=< <TABLE BGCOLOR="palegoldenrod" BORDER="0" CELLBORDER="0" CELLSPACING="0"> <TR><TD COLSPAN="2" CELLPADDING="4" ALIGN="CENTER" BGCOLOR="olivedrab4" ><FONT FACE="Helvetica Bold" COLOR="white" >{{ model.label }}{% if model.abstracts %}<BR/><<FONT FACE="Helvetica Italic">{{ model.abstracts|join:"," }}</FONT>>{% endif %}</FONT></TD></TR> {% if not disable_fields %} {% for field in model.fields %} <TR><TD ALIGN="LEFT" BORDER="0" ><FONT {% if field.blank %}COLOR="#7B7B7B" {% endif %}FACE="Helvetica {% if field.abstract %}Italic{% else %}Bold{% endif %}">{{ field.label }}</FONT ></TD> <TD ALIGN="LEFT" ><FONT {% if field.blank %}COLOR="#7B7B7B" {% endif %}FACE="Helvetica {% if field.abstract %}Italic{% else %}Bold{% endif %}">{{ field.type }}</FONT ></TD></TR> {% endfor %} {% endif %} </TABLE> >] {% endfor %} {% if use_subgraph %} } {% endif %}""") dot += '\n' + t.render(graph) for graph in graphs: t = loader.get_template_from_string("""{% for model in models %} {% for relation in model.relations %} {% if relation.needs_node %} {{ relation.target_app }}_{{ relation.target }} [label=< <TABLE BGCOLOR="palegoldenrod" BORDER="0" CELLBORDER="0" CELLSPACING="0"> <TR><TD COLSPAN="2" CELLPADDING="4" ALIGN="CENTER" BGCOLOR="olivedrab4" ><FONT FACE="Helvetica Bold" COLOR="white" >{{ relation.target }}</FONT></TD></TR> </TABLE> >] {% endif %} {{ model.app_name }}_{{ model.name }} -> {{ relation.target_app }}_{{ relation.target }} [label="{{ relation.label }}"] {{ relation.arrows }}; {% endfor %} {% endfor %}""") dot += '\n' + t.render(graph) t = loader.get_template_from_string("}") c = Context({}) dot += '\n' + t.render(c) return dot
def getAllModels(): app = apps.get_app('wine') models = apps.get_models(app) return models
def generate_dot(app_labels, **kwargs): disable_fields = kwargs.get("disable_fields", False) include_models = parse_file_or_list(kwargs.get("include_models", "")) all_applications = kwargs.get("all_applications", False) use_subgraph = kwargs.get("group_models", False) verbose_names = kwargs.get("verbose_names", False) inheritance = kwargs.get("inheritance", False) language = kwargs.get("language", None) if language is not None: activate_language(language) exclude_columns = parse_file_or_list(kwargs.get("exclude_columns", "")) exclude_models = parse_file_or_list(kwargs.get("exclude_models", "")) def skip_field(field): if exclude_columns: if verbose_names and field.verbose_name: if field.verbose_name in exclude_columns: return True if field.name in exclude_columns: return True return False t = loader.get_template_from_string( """ digraph name { fontname = "Helvetica" fontsize = 8 node [ fontname = "Helvetica" fontsize = 8 shape = "plaintext" ] edge [ fontname = "Helvetica" fontsize = 8 ] """ ) c = Context({}) dot = t.render(c) apps = [] if all_applications: apps = djApps.get_apps() for app_label in app_labels: app = djApps.get_app(app_label) if app not in apps: apps.append(app) graphs = [] for app in apps: graph = Context( { "name": '"%s"' % app.__name__, "app_name": "%s" % ".".join(app.__name__.split(".")[:-1]), "cluster_app_name": "cluster_%s" % app.__name__.replace(".", "_"), "disable_fields": disable_fields, "use_subgraph": use_subgraph, "models": [], } ) appmodels = djApps.get_models(app) abstract_models = [] for appmodel in appmodels: abstract_models = abstract_models + [ abstract_model for abstract_model in appmodel.__bases__ if hasattr(abstract_model, "_meta") and abstract_model._meta.abstract ] abstract_models = list(set(abstract_models)) # remove duplicates appmodels = abstract_models + appmodels for appmodel in appmodels: appmodel_abstracts = [ abstract_model.__name__ for abstract_model in appmodel.__bases__ if hasattr(abstract_model, "_meta") and abstract_model._meta.abstract ] # collect all attribs of abstract superclasses def getBasesAbstractFields(c): _abstract_fields = [] for e in c.__bases__: if hasattr(e, "_meta") and e._meta.abstract: _abstract_fields.extend(e._meta.fields) _abstract_fields.extend(getBasesAbstractFields(e)) return _abstract_fields abstract_fields = getBasesAbstractFields(appmodel) model = { "app_name": appmodel.__module__.replace(".", "_"), "name": appmodel.__name__, "abstracts": appmodel_abstracts, "fields": [], "relations": [], } # consider given model name ? def consider(model_name): if exclude_models and model_name in exclude_models: return False return not include_models or model_name in include_models if not consider(appmodel._meta.object_name): continue if verbose_names and appmodel._meta.verbose_name: model["label"] = appmodel._meta.verbose_name else: model["label"] = model["name"] # model attributes def add_attributes(field): if verbose_names and field.verbose_name: label = field.verbose_name else: label = field.name t = type(field).__name__ if isinstance(field, (OneToOneField, ForeignKey)): t += " ({0})".format(field.rel.field_name) # TODO: ManyToManyField, GenericRelation model["fields"].append( { "name": field.name, "label": label, "type": t, "blank": field.blank, "abstract": field in abstract_fields, } ) # Find all the real attributes. Relations are depicted as graph # edges instead of attributes attributes = [field for field in appmodel._meta.local_fields if not isinstance(field, RelatedField)] # find primary key and print it first, ignoring implicit id if # other pk exists pk = appmodel._meta.pk if not appmodel._meta.abstract and pk in attributes: add_attributes(pk) for field in attributes: if skip_field(field): continue if not field.primary_key: add_attributes(field) # FIXME: actually many_to_many fields aren't saved in this model's db table, so why should we add an attribute-line for them in the resulting graph? # if appmodel._meta.many_to_many: # for field in appmodel._meta.many_to_many: # if skip_field(field): # continue # add_attributes(field) # relations def add_relation(field, extras=""): if verbose_names and field.verbose_name: label = field.verbose_name else: label = field.name # show related field name if hasattr(field, "related_query_name"): label += " (%s)" % field.related_query_name() # handle self-relationships if field.rel.to == "self": target_model = field.model else: target_model = field.rel.to _rel = { "target_app": target_model.__module__.replace(".", "_"), "target": target_model.__name__, "type": type(field).__name__, "name": field.name, "label": label, "arrows": extras, "needs_node": True, } if _rel not in model["relations"] and consider(_rel["target"]): model["relations"].append(_rel) for field in appmodel._meta.local_fields: # excluding field redundant with inheritance relation if field.attname.endswith("_ptr_id"): continue # excluding fields inherited from abstract classes. they too # show as local_fields if field in abstract_fields: continue if skip_field(field): continue if isinstance(field, OneToOneField): add_relation(field, "[arrowhead=none, arrowtail=none]") elif isinstance(field, ForeignKey): add_relation(field, "[arrowhead=none, arrowtail=dot]") for field in appmodel._meta.local_many_to_many: if skip_field(field): continue if isinstance(field, ManyToManyField): if getattr(field, "creates_table", False) or ( # django 1.1. hasattr(field.rel.through, "_meta") and field.rel.through._meta.auto_created ): # django 1.2 add_relation(field, "[arrowhead=dot arrowtail=dot, dir=both]") elif isinstance(field, GenericRelation): add_relation(field, mark_safe('[style="dotted", arrowhead=normal, arrowtail=normal, dir=both]')) if inheritance: # add inheritance arrows for parent in appmodel.__bases__: if hasattr(parent, "_meta"): # parent is a model l = "multi-table" if parent._meta.abstract: l = "abstract" if appmodel._meta.proxy: l = "proxy" l += r"\ninheritance" _rel = { "target_app": parent.__module__.replace(".", "_"), "target": parent.__name__, "type": "inheritance", "name": "inheritance", "label": l, "arrows": "[arrowhead=empty, arrowtail=none]", "needs_node": True, } # TODO: seems as if abstract models aren't part of # models.getModels, which is why they are printed by # this without any attributes. if _rel not in model["relations"] and consider(_rel["target"]): model["relations"].append(_rel) graph["models"].append(model) graphs.append(graph) nodes = [] for graph in graphs: nodes.extend([e["name"] for e in graph["models"]]) for graph in graphs: # don't draw duplication nodes because of relations for model in graph["models"]: for relation in model["relations"]: if relation["target"] in nodes: relation["needs_node"] = False # render templates t = loader.get_template_from_string( """{% if use_subgraph %} subgraph {{ cluster_app_name }} { label=< <TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0"> <TR><TD COLSPAN="2" CELLPADDING="4" ALIGN="CENTER" ><FONT FACE="Helvetica Bold" COLOR="Black" POINT-SIZE="12" >{{ app_name }}</FONT></TD></TR> </TABLE> > color=olivedrab4 style="rounded" {% endif %} {% for model in models %} {{ model.app_name }}_{{ model.name }} [label=< <TABLE BGCOLOR="palegoldenrod" BORDER="0" CELLBORDER="0" CELLSPACING="0"> <TR><TD COLSPAN="2" CELLPADDING="4" ALIGN="CENTER" BGCOLOR="olivedrab4" ><FONT FACE="Helvetica Bold" COLOR="white" >{{ model.label }}{% if model.abstracts %}<BR/><<FONT FACE="Helvetica Italic">{{ model.abstracts|join:"," }}</FONT>>{% endif %}</FONT></TD></TR> {% if not disable_fields %} {% for field in model.fields %} <TR><TD ALIGN="LEFT" BORDER="0" ><FONT {% if field.blank %}COLOR="#7B7B7B" {% endif %}FACE="Helvetica {% if field.abstract %}Italic{% else %}Bold{% endif %}">{{ field.label }}</FONT ></TD> <TD ALIGN="LEFT" ><FONT {% if field.blank %}COLOR="#7B7B7B" {% endif %}FACE="Helvetica {% if field.abstract %}Italic{% else %}Bold{% endif %}">{{ field.type }}</FONT ></TD></TR> {% endfor %} {% endif %} </TABLE> >] {% endfor %} {% if use_subgraph %} } {% endif %}""" ) dot += "\n" + t.render(graph) for graph in graphs: t = loader.get_template_from_string( """{% for model in models %} {% for relation in model.relations %} {% if relation.needs_node %} {{ relation.target_app }}_{{ relation.target }} [label=< <TABLE BGCOLOR="palegoldenrod" BORDER="0" CELLBORDER="0" CELLSPACING="0"> <TR><TD COLSPAN="2" CELLPADDING="4" ALIGN="CENTER" BGCOLOR="olivedrab4" ><FONT FACE="Helvetica Bold" COLOR="white" >{{ relation.target }}</FONT></TD></TR> </TABLE> >] {% endif %} {{ model.app_name }}_{{ model.name }} -> {{ relation.target_app }}_{{ relation.target }} [label="{{ relation.label }}"] {{ relation.arrows }}; {% endfor %} {% endfor %}""" ) dot += "\n" + t.render(graph) t = loader.get_template_from_string("}") c = Context({}) dot += "\n" + t.render(c) return dot
def handle(self, *app_labels, **options): from django.apps import apps indent = options.get('indent', None) using = options.get('database', DEFAULT_DB_ALIAS) connection = connections[using] excludes = options.get('exclude',[]) show_traceback = options.get('traceback', False) use_natural_foreign_keys = options.get('use_natural_foreign_keys', False) use_base_manager = options.get('use_base_manager', False) excluded_apps = set() excluded_models = set() for exclude in excludes: if '.' in exclude: app_label, model_name = exclude.split('.', 1) model_obj = apps.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 = apps.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 = OrderedDict((app, None) for app in apps.get_apps() if app not in excluded_apps) else: app_list = OrderedDict() for label in app_labels: try: app_label, model_label = label.split('.') try: app = apps.get_app(app_label) except ImproperlyConfigured: raise CommandError("Unknown application: %s" % app_label) if app in excluded_apps: continue model = apps.get_model(app_label, model_label) if model is None: raise CommandError("Unknown model: %s.%s" % (app_label, model_label)) if app in list(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 = apps.get_app(app_label) except ImproperlyConfigured: raise CommandError("Unknown application: %s" % app_label) if app in excluded_apps: continue app_list[app] = None # Now collate the objects to be serialized. objects = [] for model in sort_dependencies(list(app_list.items())): if model in excluded_models: continue if not model._meta.proxy and router.allow_migrate(using, model): if use_base_manager: objects.extend(model._base_manager.using(using).all()) else: objects.extend(model._default_manager.using(using).all()) try: serializer = XMLExportSerializer() return serializer.serialize(objects, indent=indent, use_natural_foreign_keys=use_natural_foreign_keys) except Exception as e: if show_traceback: raise raise CommandError("Unable to serialize database: %s" % e)