= Converting Django models into Graphviz DOT files = Inspired by [http://www.hackdiary.com/archives/000093.html this nice hack by Matt Biddulph] I set out to create a similar thing for Django models. Below is an initial implementation, and here are some results generated with the OS X version of Graphviz: * Graphviz DOT files for the Zyons project: [http://cavedoni.com/2006/08/zyons-comment.dot comment] [http://cavedoni.com/2006/08/zyons-event.dot event] [http://cavedoni.com/2006/08/zyons-forum.dot forum] [http://cavedoni.com/2006/08/zyons-openid.dot openid] [http://cavedoni.com/2006/08/zyons-prefs.dot prefs] [http://cavedoni.com/2006/08/zyons-sessions.dot sessions] [http://cavedoni.com/2006/08/zyons-tag.dot tag] * Resulting graphs in PDF: [http://cavedoni.com/2006/08/zyons-comment.pdf comment] [http://cavedoni.com/2006/08/zyons-event.pdf event] [http://cavedoni.com/2006/08/zyons-forum.pdf forum] [http://cavedoni.com/2006/08/zyons-openid.pdf openid] [http://cavedoni.com/2006/08/zyons-prefs.pdf prefs] [http://cavedoni.com/2006/08/zyons-sessions.pdf sessions] [http://cavedoni.com/2006/08/zyons-tag.pdf tag] * Other samples: * [http://cavedoni.com/2006/08/camera-001.dot generated dot file]: resulting image in [http://cavedoni.com/2006/08/camera-001.pdf PDF], {{{ #!html PNG }}} * [http://cavedoni.com/2006/08/mincer-001.dot generated dot file]: resulting image in [http://cavedoni.com/2006/08/mincer-001.pdf PDF], {{{ #!html PNG }}} You might also be interested in [http://www.exit66.com/diagram.zip this Django app by Andrew Barilla ] from which I borrowed some ideas, that displays the graphviz results directly from the web. {{{ #!python #!/usr/bin/python """Django model to DOT (Graphviz) converter by Antonio Cavedoni Make sure your DJANGO_SETTINGS_MODULE is set to your project and call the script like this: $ python modelviz.py > .dot Changelog 0.4 Fixed OneToOneField support (thanks, limodou) 0.3 Added support for GenericRelation and OneToOneField 0.2 Changed display (shape="record", thanks Malcolm Tredinnick), fixed arrow direction, added display of model attributes (thanks, Russell Keith-Magee) 0.1 First release. """ __version__ = "0.4" __license__ = "Python" __author__ = "Antonio Cavedoni ", "limodou " ] from django.db import models from django.db.models import get_models from django.db.models.fields.related import \ ForeignKey, OneToOneField, ManyToManyField from django.db.models.fields.generic import GenericRelation def generate_dot(app_label): app = models.get_app(app_label) print "digraph %s {" % ('"' + app.__name__ + '"') print """ fontname = "Helvetica" fontsize = 8 node [ fontname = "Helvetica" fontsize = 8 shape = "record" ] edge [ fontname = "Helvetica" fontsize = 8 ] """ for o in get_models(app): nodes = [] nodes.append(""" %s [ label = "{%s |""" % (o.__name__, o.__name__)) # model attributes for field in o._meta.fields: nodes.append('%s : %s\\l' % (field.name, type(field).__name__)) if o._meta.many_to_many: for field in o._meta.many_to_many: nodes.append('%s : %s\\l' % (field.name, type(field).__name__)) nodes.append(""" }"\n]\n""") print "".join(nodes) # relations rel = [] for field in o._meta.fields: if isinstance(field, ForeignKey): _rel = ' %s -> %s [label="%s"];' % \ (o.__name__, field.rel.to.__name__, type(field).__name__) if _rel not in rel: rel.append(_rel) elif isinstance(field, OneToOneField): _rel = ' %s -> %s [label="%s"] [arrowhead=none arrowtail=none];' % (o.__name__, field.rel.to.__name__, type(field).__name__) if _rel not in rel: rel.append(_rel) for field in o._meta.fields: if isinstance(field, ForeignKey): _rel = ' %s -> %s [label="%s"];' % \ (o.__name__, field.rel.to.__name__, type(field).__name__) if _rel not in rel: rel.append(_rel) if o._meta.many_to_many: for field in o._meta.many_to_many: if isinstance(field, ManyToManyField): _rel = ' %s -> %s [label="%s"] [arrowhead=normal arrowtail=normal];' % \ (o.__name__, field.rel.to.__name__, type(field).__name__) if _rel not in rel: rel.append(_rel) if isinstance(field, GenericRelation): _rel = ' %s -> %s [label="%s"] [style="dotted"] [arrowhead=normal arrowtail=normal];' % \ (o.__name__, field.rel.to.__name__, type(field).__name__) if _rel not in rel: rel.append(_rel) print "\n".join(rel) print "}" if __name__ == "__main__": import sys app_label = sys.argv[1] generate_dot(app_label) }}}