Changes between Version 18 and Version 19 of DjangoGraphviz


Ignore:
Timestamp:
10/19/06 10:40:58 (8 years ago)
Author:
verbosus
Comment:

Refactored page, added link to code in subversion repository, added note about outdated examples

Legend:

Unmodified
Added
Removed
Modified
  • DjangoGraphviz

    v18 v19  
    11= Converting Django models into Graphviz DOT files =
    22
    3 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:
     3Inspired by [http://www.hackdiary.com/archives/000093.html this nice hack by Matt Biddulph], this is a Python script that generates a Graphviz DOT file for quick visualizations of Django model definitions.
    44
    5  * 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]
    6  * 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]
     5== Source code ==
    76
    8  * Other samples:
    9    * [http://cavedoni.com/2006/08/camera-001.dot generated dot file]: resulting image in [http://cavedoni.com/2006/08/camera-001.pdf PDF],
    10 {{{
    11 #!html
    12 <a href="http://code.djangoproject.com/attachment/wiki/DjangoGraphviz/camera-001.png">PNG</a>
    13 }}}
    14    * [http://cavedoni.com/2006/08/mincer-001.dot generated dot file]: resulting image in [http://cavedoni.com/2006/08/mincer-001.pdf PDF],
    15 {{{
    16 #!html
    17 <a href="http://code.djangoproject.com/attachment/wiki/DjangoGraphviz/mincer-001.png">PNG</a>
    18 }}}
     7[http://unicoders.org/code/django/trunk/utils/modelviz.py View online] or [http://code.unicoders.org/django/trunk/utils/modelviz.py download from Subversion repository] (you could also set it as a svn:external on your repository to keep up to date with the latest revisons.)
    198
    20 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.
     9== Examples ==
    2110
    22 {{{
    23 #!python
    24 #!/usr/bin/python
    25 """Django model to DOT (Graphviz) converter
    26 by Antonio Cavedoni <antonio@cavedoni.org>
     11'''Nota bene''': this samples are generated from an old version of the script, 0.4, which you can download from [http://code.djangoproject.com/wiki/DjangoGraphviz?version=10 here]. The script is currently undergoing some refactoring.
    2712
    28 Make sure your DJANGO_SETTINGS_MODULE is set to your project and call
    29 the script like this:
    30 
    31   $ python modelviz.py <app_label> > <filename>.dot
    32 
    33 Changelog
    34 
    35 0.5.1
    36 Got rid of print statements, now the generate_dot() function returns
    37 a string with the file contents
    38 
    39 0.5
    40 Cleaned up code, now the relationship arrows start from the
    41 correct model attribute position
    42 
    43 0.4
    44 Fixed OneToOneField support (thanks, limodou)
    45 
    46 0.3
    47 Added support for GenericRelation and OneToOneField
    48 
    49 0.2
    50 Changed display (shape="record", thanks Malcolm Tredinnick),
    51 fixed arrow direction, added display of model attributes
    52 (thanks, Russell Keith-Magee)
    53 
    54 0.1
    55 First release.
    56 """
    57 
    58 __version__ = "0.5.1"
    59 __svnid__ = "$Id: modelviz.py 4 2006-08-06 19:48:42Z verbosus $"
    60 __license__ = "Python"
    61 __author__ = "Antonio Cavedoni <http://cavedoni.com/>"
    62 __contributors__ = [
    63    "Stefano J. Attardi <http://attardi.org/>",
    64    "limodou <http://www.donews.net/limodou/>"
    65    ]
    66 
    67 from django.db import models
    68 from django.db.models import get_models
    69 from django.db.models.fields.related import \
    70     ForeignKey, OneToOneField, ManyToManyField
    71 from django.db.models.fields.generic import GenericRelation
    72 
    73 def generate_dot(app_label):
    74    app = models.get_app(app_label)
    75 
    76    graph = []
    77    graph.append("digraph %s {" % ('"' + app.__name__ + '"'))
    78    graph.append("""  fontname = "Helvetica"
    79   fontsize = 8
    80      
    81   node [
    82     fontname = "Helvetica"
    83     fontsize = 8
    84     shape = "record"
    85   ]
    86    edge [
    87     fontname = "Helvetica"
    88     fontsize = 8
    89   ]
    90 """)
    91    for o in get_models(app):
    92       graph.append(""" subgraph cluster_%(model)s {
    93   shape = "record";
    94   label = "%(model)s";
    95   fontname = "Helvetica Bold";
    96   fontsize = 10;
    97   labelfontcolor = "black";
    98   %(model)s [label = "{""" % {'model': o.__name__})
    99 
    100       # model attributes
    101       def add_attributes():
    102          graph.append("<%(model)s_%(field)s>%(field)s : %(related)s|" % \
    103                       {'model': o.__name__, 'field': field.name,
    104                        'related': type(field).__name__})
    105 
    106       for field in o._meta.fields:
    107          add_attributes()
    108          
    109       if o._meta.many_to_many:
    110          for field in o._meta.many_to_many:
    111             add_attributes()
    112 
    113       graph.append(""" }"] [color="white" shape="record"];\n }\n""")
    114 
    115       # relations
    116       rel = []
    117       def add_relation(extras=""):
    118          _rel = """ %(model)s:%(model)s_%(field)s -> %(related)s
    119          [label="%(relationship)s"] %(extras)s;\n""" % {
    120             'model': o.__name__, 'field': field.name,
    121             'related': field.rel.to.__name__,
    122             'relationship': type(field).__name__,
    123             'extras': extras}
    124          if _rel not in rel:
    125             rel.append(_rel)
    126 
    127       for field in o._meta.fields:
    128          if isinstance(field, ForeignKey):
    129             add_relation()
    130          elif isinstance(field, OneToOneField):
    131             add_relation("[arrowhead=none arrowtail=none]")
    132 
    133       if o._meta.many_to_many:
    134          for field in o._meta.many_to_many:
    135             if isinstance(field, ManyToManyField):
    136                add_relation("[arrowhead=normal arrowtail=normal]")
    137             elif isinstance(field, GenericRelation):
    138                add_relation(
    139                   '[style="dotted"] [arrowhead=normal arrowtail=normal]')
    140       graph.append("".join(rel))
    141 
    142    graph.append('}')
    143    return "".join(graph)
    144 
    145 if __name__ == "__main__":
    146    import sys
    147    app_label = sys.argv[1]
    148    print generate_dot(app_label)
    149 }}}
    150 
    151 = Examples =
    152 
    153 Camera
     13=== Camera website (yet unpublished) ===
    15414
    15515{{{
     
    15818}}}
    15919
    160 Mincer
     20=== [http://www.mincer.it/ MC Minerali Ceramici] ===
    16121
    16222{{{
     
    16525}}}
    16626
    167 = Feedback =
    168  * favo: I have a large app(some model has lots fields). The generated png file is too large. Maybe this tools could work in a concision mode which only contain related field and omit other fields of a model.
    169  * elvstone: How did you manage to get the edges to only reach the edge of the subgraphs? I get
    170 {{{
    171 #!html
    172 <a href="http://bob.dose.se/watchtower.png">this</a>
    173 }}}
    174 result, which isn't very nice. I've digged through the GraphViz docs/mailing lists without luck :(
     27=== Other examples ===
     28
     29 * [http://zyons.com/ Zyons project]
     30   * 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]
     31   * 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]
     32
     33== Other References ==
     34
     35You 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.
     36
     37== Feedback ==
     38
     39Please direct all feedback to [mailto:antonio@cavedoni.org Antonio Cavedoni].
Back to Top