Login

Improved command to generate UML diagrams of whole project or specified apps

Author:
nikolajusk
Posted:
October 7, 2010
Language:
Python
Version:
1.2
Score:
0 (after 0 ratings)

example of use:

  1. python manage.py yuml yourapp yoursecondapp --scruffy -s 75 -o test.png

  2. python manage.py yuml justoneapp --scruffy -o test.pdf

  3. generate whole project yuml : python manage.py yuml -a -o test.jpg

  4. python manage.py yuml auth contenttypes sessions admin -o test.pdf

github repository

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
from django.core.management.base import BaseCommand, CommandError
from optparse import make_option
from django.db.models.loading import get_models, get_apps, get_app
from django.core.exceptions import ImproperlyConfigured
import os

class Command(BaseCommand):
  option_list = BaseCommand.option_list + (
    make_option('--all-applications', '-a', action='store_true', dest='all_applications',
      help='Automaticly include all applications from INSTALLED_APPS'),
    make_option('--output', '-o', action='store', dest='outputfile',
      help='Render output file. Type of output dependend on file extensions. Use png,jpg or pdf to render graph to image to.'),
    make_option('--scale', '-s', action='store', dest='scale',
      help='Set a scale percentage. Applies only for -o'),
    make_option('--scruffy','', action='store_true', dest='scruffy',
      help='Make a scuffy diagram')
  )
  args = '[appname appname]'
  help = 'Generating model class diagram for yuml.me'
  label = 'application name'
  
  yuml = ''
  YUMLME_URL="http://yuml.me/diagram/"
    
  def handle(self, *args, **options):
    if len(args) < 1 and not options['all_applications']:
      raise CommandError("need one or more arguments for appname")
    self.generate_yuml(args, **options)
    if options['outputfile']:
      self.render_to(**options)
    else:
      self.print_output()
  
  def render_to(self, **options):
    import urllib2,urllib
    filename = options['outputfile']
    extension = os.path.splitext(filename)[1]
    url_yuml = urllib.quote(self.yuml.strip().replace("\n",", "))

    if options['scale']:
      self.YUMLME_URL = self.YUMLME_URL + "scale:%s" % options['scale']
    if options['scruffy']:
      if self.YUMLME_URL[-1]!="/":
        self.YUMLME_URL += ";"
      self.YUMLME_URL = self.YUMLME_URL + "scruffy"
    
    try:
      if self.YUMLME_URL[-1]=="/":
        self.YUMLME_URL = self.YUMLME_URL[:-1]
      r = urllib2.urlopen("%s/class/%s%s" % (self.YUMLME_URL, url_yuml, extension))
    except urllib2.HTTPError, e:
      raise CommandError("Error occured while generating %s, %s" % (extension,e))
    
    resp = r.read()
    f = open(options['outputfile'],'w+')
    f.write(resp)
    f.close()
  
  def print_output(self):
    print self.yuml.encode('utf-8')
  
  def generate_yuml(self,app_labels,**options):
    imported_objects = {}        

    if not options['all_applications']:
      for application in app_labels:
        try:
          app_mod = get_app(application)
          app_models = get_models(app_mod)
          if not app_models:
            continue
          model_labels = ", ".join([model.__name__ for model in app_models])
          for model in app_models:
            try:
              imported_objects[model.__name__] = getattr(__import__(app_mod.__name__, {}, {}, model.__name__), model.__name__)
            except AttributeError, e:
              continue
        except ImproperlyConfigured, e:
          raise CommandError("Specified application not found: %s" % e)
    else:
      for app_mod in get_apps():
        app_models = get_models(app_mod)
        if not app_models:
          continue
        model_labels = ", ".join([model.__name__ for model in app_models])
        for model in app_models:
          try:
            imported_objects[model.__name__] = getattr(__import__(app_mod.__name__, {}, {}, model.__name__), model.__name__)
          except AttributeError, e:
            continue
    
    for model_name in imported_objects:
      model = imported_objects[model_name]
      self.yuml += "[%s|" % (model._meta.module_name)
      relations = {}
      for field in model._meta.fields:
        if field.__class__.__name__=='ForeignKey':
          relations[field.attname] = field.related.parent_model._meta.module_name
        self.yuml += "%s (%s);" % (field.attname, field.__class__.__name__)
      self.yuml += "]\n" 
      if len(relations)>0:
        for column in relations:
          self.yuml += "[%s]-%s>[%s]\n"% (model._meta.module_name,column,relations[column])

More like this

  1. Template tag - list punctuation for a list of items by shapiromatron 10 months, 2 weeks ago
  2. JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 10 months, 3 weeks ago
  3. Serializer factory with Django Rest Framework by julio 1 year, 5 months ago
  4. Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 6 months ago
  5. Help text hyperlinks by sa2812 1 year, 7 months ago

Comments

Please login first before commenting.