= 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:
* [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
Example:
$ python modelviz.py camera > foo.dot
"""
from django.db import models
from django.db.models import get_models
from django.db.models.fields.related import \
ForeignKey, OneToOneField, ManyToManyField
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__))
# members
for field in o._meta.fields:
nodes.append("%s : %s\\l" % (field.name, type(field).__name__))
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)
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)
print "\n".join(rel)
print "}"
if __name__ == "__main__":
import sys
app_label = sys.argv[1]
generate_dot(app_label)
}}}