def runjobs_by_signals(self, when, options): """ Run jobs from the signals """ # Thanks for Ian Holsman for the idea and code from django_extensions.compat import get_apps from django_extensions.management import signals from django.conf import settings verbosity = int(options.get('verbosity', 1)) for app_name in settings.INSTALLED_APPS: try: __import__(app_name + '.management', '', '', ['']) except ImportError: pass for app in get_apps(): if verbosity > 1: app_name = '.'.join(app.__name__.rsplit('.')[:-1]) print("Sending %s job signal for: %s" % (when, app_name)) if when == 'minutely': signals.run_minutely_jobs.send(sender=app, app=app) elif when == 'quarter_hourly': signals.run_quarter_hourly_jobs.send(sender=app, app=app) elif when == 'hourly': signals.run_hourly_jobs.send(sender=app, app=app) elif when == 'daily': signals.run_daily_jobs.send(sender=app, app=app) elif when == 'weekly': signals.run_weekly_jobs.send(sender=app, app=app) elif when == 'monthly': signals.run_monthly_jobs.send(sender=app, app=app) elif when == 'yearly': signals.run_yearly_jobs.send(sender=app, app=app)
def get_models(app_labels): """ Gets a list of models for the given app labels, with some exceptions. TODO: If a required model is referenced, it should also be included. Or at least discovered with a get_or_create() call. """ # These models are not to be output, e.g. because they can be generated automatically # TODO: This should be "appname.modelname" string EXCLUDED_MODELS = (ContentType, ) models = [] # If no app labels are given, return all if not app_labels: for app in get_apps(): models += [m for m in get_models_compat(app) if m not in EXCLUDED_MODELS] return models # Get all relevant apps for app_label in app_labels: # If a specific model is mentioned, get only that model if "." in app_label: app_label, model_name = app_label.split(".", 1) models.append(get_model_compat(app_label, model_name)) # Get all models for a given app else: models += [m for m in get_models_for_app(app_label) if m not in EXCLUDED_MODELS] return models
def handle(self, *args, **kwargs): self.style = color_style() installed_apps = dict( (a.__name__.rsplit('.', 1)[0], a) for a in get_apps()) # Make sure we always have args if not args: args = [False] app = installed_apps.get(args[0]) if not app: print( self.style.WARN( 'This command requires an existing app name as argument')) print(self.style.WARN('Available apps:')) for app in sorted(installed_apps): print(self.style.WARN(' %s' % app)) sys.exit(1) model_res = [] for arg in args[1:]: model_res.append(re.compile(arg, re.IGNORECASE)) self.handle_app(app, model_res, **kwargs)
def get_models(app_labels): """ Gets a list of models for the given app labels, with some exceptions. TODO: If a required model is referenced, it should also be included. Or at least discovered with a get_or_create() call. """ # These models are not to be output, e.g. because they can be generated automatically # TODO: This should be "appname.modelname" string EXCLUDED_MODELS = (ContentType, ) models = [] # If no app labels are given, return all if not app_labels: for app in get_apps(): models += [ m for m in get_models_compat(app) if m not in EXCLUDED_MODELS ] return models # Get all relevant apps for app_label in app_labels: # If a specific model is mentioned, get only that model if "." in app_label: app_label, model_name = app_label.split(".", 1) models.append(get_model_compat(app_label, model_name)) # Get all models for a given app else: models += [ m for m in get_models_for_app(app_label) if m not in EXCLUDED_MODELS ] return models
def handle(self, *args, **kwargs): self.style = color_style() installed_apps = dict((a.__name__.rsplit('.', 1)[0], a) for a in get_apps()) # Make sure we always have args app = kwargs.pop('app')[0] if not installed_apps.get(app): print(self.style.WARN('This command requires an existing app name as argument')) print(self.style.WARN('Available apps:')) for app in sorted(installed_apps): print(self.style.WARN(' %s' % app)) sys.exit(1) model_res = [] for arg in args[1:]: model_res.append(re.compile(arg, re.IGNORECASE)) self.handle_app(app, model_res, **kwargs)
def handle(self, *args, **kwargs): self.style = color_style() installed_apps = dict((a.__name__.rsplit(".", 1)[0], a) for a in get_apps()) # Make sure we always have args if not args: args = [False] app = installed_apps.get(args[0]) if not app: print(self.style.WARN("This command requires an existing app name as argument")) print(self.style.WARN("Available apps:")) for app in sorted(installed_apps): print(self.style.WARN(" %s" % app)) sys.exit(1) model_res = [] for arg in args[1:]: model_res.append(re.compile(arg, re.IGNORECASE)) self.handle_app(app, model_res, **kwargs)
def generate_dot(app_labels, **kwargs): cli_options = kwargs.get('cli_options', None) 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', True) relations_as_fields = kwargs.get("relations_as_fields", True) sort_fields = kwargs.get("sort_fields", True) 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 apps = [] if all_applications: apps = get_apps() for app_label in app_labels: app = models.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(".", "_"), 'models': [] }) appmodels = 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 elif include_models and model_name not in include_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.decode("utf8") else: model['label'] = model['name'] # model attributes def add_attributes(field): if verbose_names and field.verbose_name: label = field.verbose_name.decode("utf8") if label.islower(): label = label.capitalize() 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, 'relation': isinstance(field, RelatedField), 'primary_key': field.primary_key, }) attributes = [field for field in appmodel._meta.local_fields] if not relations_as_fields: # Find all the 'real' attributes. Relations are depicted as graph edges instead of attributes attributes = [field for field in attributes if not isinstance(field, RelatedField)] # find primary key and print it first, ignoring implicit id if other pk exists pk = appmodel._meta.pk if pk and not appmodel._meta.abstract and pk in attributes: add_attributes(pk) for field in attributes: if skip_field(field): continue if pk and field == pk: continue add_attributes(field) if sort_fields: model['fields'] = sorted(model['fields'], key=lambda field: (not field['primary_key'], not field['relation'], field['label'])) # 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.decode("utf8") if label.islower(): label = label.capitalize() else: label = field.name # show related field name if hasattr(field, 'related_query_name'): related_query_name = field.related_query_name() if verbose_names and related_query_name.islower(): related_query_name = related_query_name.replace('_', ' ').capitalize() label += ' (%s)' % related_query_name # handle self-relationships and lazy-relationships if isinstance(field.rel.to, six.string_types): if field.rel.to == 'self': target_model = field.model else: raise Exception("Lazy relationship for model (%s) must be explicit for field (%s)" % (field.model.__name__, field.name)) 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: if field.attname.endswith('_ptr_id'): # excluding field redundant with inheritance relation continue if field in abstract_fields: # excluding fields inherited from abstract classes. they too show as local_fields continue if skip_field(field): continue if isinstance(field, OneToOneField): add_relation(field, '[arrowhead=none, arrowtail=none, dir=both]') elif isinstance(field, ForeignKey): add_relation(field, '[arrowhead=none, arrowtail=dot, dir=both]') 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, dir=both]', '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) if graph['models']: graphs.append(graph) nodes = [] for graph in graphs: nodes.extend([e['name'] for e in graph['models']]) for graph in graphs: for model in graph['models']: for relation in model['relations']: if relation['target'] in nodes: relation['needs_node'] = False now = datetime.datetime.now() t = loader.get_template('django_extensions/graph_models/digraph.dot') if not isinstance(t, Template) and not (hasattr(t, 'template') and isinstance(t.template, Template)): raise Exception("Default Django template loader isn't used. " "This can lead to the incorrect template rendering. " "Please, check the settings.") c = Context({ 'created_at': now.strftime("%Y-%m-%d %H:%M"), 'cli_options': cli_options, 'disable_fields': disable_fields, 'use_subgraph': use_subgraph, 'graphs': graphs, }) dot = t.render(c) return dot
def generate_dot(app_labels, **kwargs): cli_options = kwargs.get('cli_options', None) 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', True) relations_as_fields = kwargs.get("relations_as_fields", True) sort_fields = kwargs.get("sort_fields", True) 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 apps = [] if all_applications: apps = get_apps() for app_label in app_labels: app = models.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(".", "_"), 'models': [] }) appmodels = 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 elif include_models and model_name not in include_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.decode("utf8") else: model['label'] = model['name'] # model attributes def add_attributes(field): if verbose_names and field.verbose_name: label = field.verbose_name.decode("utf8") if label.islower(): label = label.capitalize() 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, 'relation': isinstance(field, RelatedField), 'primary_key': field.primary_key, }) attributes = [field for field in appmodel._meta.local_fields] if not relations_as_fields: # Find all the 'real' attributes. Relations are depicted as graph edges instead of attributes attributes = [ field for field in attributes if not isinstance(field, RelatedField) ] # find primary key and print it first, ignoring implicit id if other pk exists pk = appmodel._meta.pk if pk and not appmodel._meta.abstract and pk in attributes: add_attributes(pk) for field in attributes: if skip_field(field): continue if pk and field == pk: continue add_attributes(field) if sort_fields: model['fields'] = sorted(model['fields'], key=lambda field: (not field['primary_key'], not field[ 'relation'], field['label'])) # 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.decode("utf8") if label.islower(): label = label.capitalize() else: label = field.name # show related field name if hasattr(field, 'related_query_name'): related_query_name = field.related_query_name() if verbose_names and related_query_name.islower(): related_query_name = related_query_name.replace( '_', ' ').capitalize() label += ' (%s)' % related_query_name # handle self-relationships and lazy-relationships if isinstance(field.rel.to, six.string_types): if field.rel.to == 'self': target_model = field.model else: raise Exception( "Lazy relationship for model (%s) must be explicit for field (%s)" % (field.model.__name__, field.name)) 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: if field.attname.endswith( '_ptr_id' ): # excluding field redundant with inheritance relation continue if field in abstract_fields: # excluding fields inherited from abstract classes. they too show as local_fields continue if skip_field(field): continue if isinstance(field, OneToOneField): add_relation(field, '[arrowhead=none, arrowtail=none, dir=both]') elif isinstance(field, ForeignKey): add_relation(field, '[arrowhead=none, arrowtail=dot, dir=both]') 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, dir=both]', '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) if graph['models']: graphs.append(graph) nodes = [] for graph in graphs: nodes.extend([e['name'] for e in graph['models']]) for graph in graphs: for model in graph['models']: for relation in model['relations']: if relation['target'] in nodes: relation['needs_node'] = False now = datetime.datetime.now() t = loader.get_template('django_extensions/graph_models/digraph.dot') if not isinstance(t, Template) and not (hasattr(t, 'template') and isinstance(t.template, Template)): raise Exception("Default Django template loader isn't used. " "This can lead to the incorrect template rendering. " "Please, check the settings.") c = Context({ 'created_at': now.strftime("%Y-%m-%d %H:%M"), 'cli_options': cli_options, 'disable_fields': disable_fields, 'use_subgraph': use_subgraph, 'graphs': graphs, }) dot = t.render(c) return dot