Management Command to Visualize Model Relationships
Django
2011-06-17 07:09 (15 years ago)

# -*- coding: utf-8 -*-
"""
Django management command to visualize model relations
management/commands/view_models_relation.py
./manage.py view_models_relation
+ django.contrib.auth.models.Group
+ django.contrib.auth.models.User
| + django.contrib.auth.models.Message
| + django.contrib.admin.models.LogEntry
+ django.contrib.contenttypes.models.ContentType
| + django.contrib.auth.models.Permission
| + django.contrib.admin.models.LogEntry
+ django.contrib.sessions.models.Session
+ django.contrib.sites.models.Site
+ south.models.MigrationHistory
"""
from optparse import make_option
from django.core.management.base import BaseCommand
from django.db import models
from django.utils.encoding import smart_str
from django.conf import settings
from django.utils.importlib import import_module
class Command(BaseCommand):
help = 'print model relation'
args = '<app_name>'
option_list = BaseCommand.option_list + (
make_option('--verbose',
action='store_true',
dest='verbose',
default=False,
help='Verbose message output'),
)
def echo(self, message):
"""
Example: self.echo(self.style.NOTICE('NG!'))
"""
self.stdout.write(smart_str(message, errors='ignore'))
self.stdout.write('\n')
self.stdout.flush()
def echo_verbose(self, message):
if self._verbose:
return self.echo(message)
def handle(self, app_label=None, **options):
self._verbose=options.get('verbose', False)
# Import APP
for app_name in settings.INSTALLED_APPS:
try:
import_module('.management', app_name)
except ImportError as exc:
msg = exc.args[0]
if not msg.startswith('No module named') or 'management' not in msg:
raise
if app_label:
app_list = [models.get_app(app_label)]
else:
app_list = models.get_apps()
self.childs_dict = {} # List of children
#self.parents_dict = {} # List of parents
primitive_models = [] # No relations at all
for app in app_list:
if not app_label:
self.echo_verbose('=' * 50)
self.echo_verbose('App: %s' % app)
app_models = models.get_models(app)
if not app_models:
self.echo_verbose('No app models.')
for app_model in app_models:
self.echo_verbose('-' * 50)
app_model_name = self.get_model_path(app_model)
self.echo_verbose('app_model_name=%s' % app_model_name)
has_parent = False
for field in app_model._meta.fields:
field_class_name = field.__class__.__name__
if field_class_name == 'ForeignKey' or \
field_class_name == 'OneToOneField' or \
field_class_name == 'ManyToManyField':
self.echo_verbose('related_field: %s' % field.name)
related_model = field.related.parent_model
rmn = self.get_model_path(related_model)
self.echo_verbose('related_model: %s' % rmn)
self.append_dict_list(self.childs_dict, rmn, app_model_name)
#self.append_dict_list(self.parents_dict, app_model_name, rmn)
has_parent = True
if not has_parent:
primitive_models.append(app_model_name)
for primitive_model in primitive_models:
self.print_child(primitive_model)
def print_child(self, model_name, depth=0):
indent = ("| " * depth)
self.echo(indent +"+ "+ model_name)
if model_name in self.childs_dict:
child_models = self.childs_dict[model_name]
for child_model in child_models:
if child_model == model_name:
self.echo(indent +"+ " + child_model + " (self relation)")
else:
self.print_child(child_model, depth=depth+1)
def append_dict_list(self, d, k, v):
"""
Dictionary d has a list as its value.
Add an item to that list. If it doesn't exist, create a new list.
"""
if k in d:
d[k].append(v)
else:
d[k] = [v]
def get_model_path(self, model_class):
return "%s.%s" % (model_class.__module__, model_class.__name__)
Please rate this article (No signup or login required)
Currently unrated
The author runs the application development company Cyberneura.
We look forward to discussing your development needs.
We look forward to discussing your development needs.