Changeset 51
- Timestamp:
- 11/01/06 21:38:57 (2 years ago)
- Files:
-
- 1 modified
-
django/trunk/utils/modelviz.py (modified) (7 diffs)
Legend:
- Unmodified
- Added
- Removed
-
django/trunk/utils/modelviz.py
r38 r51 1 #!/usr/bin/ python1 #!/usr/bin/env python 2 2 """Django model to DOT (Graphviz) converter 3 3 by Antonio Cavedoni <antonio@cavedoni.org> … … 6 6 the script like this: 7 7 8 $ python modelviz.py <app_label> > <filename>.dot 9 10 Changelog 11 12 0.5.1 13 Got rid of print statements, now the generate_dot() function returns 14 a string with the file contents 15 16 0.5 17 Cleaned up code, now the relationship arrows start from the 18 correct model attribute position 19 20 0.4 21 Fixed OneToOneField support (thanks, limodou) 22 23 0.3 24 Added support for GenericRelation and OneToOneField 25 26 0.2 27 Changed display (shape="record", thanks Malcolm Tredinnick), 28 fixed arrow direction, added display of model attributes 29 (thanks, Russell Keith-Magee) 30 31 0.1 32 First release. 8 $ python modelviz.py <app_label> > <filename>.dot 33 9 """ 34 10 35 __version__ = "0. 5.1"11 __version__ = "0.6" 36 12 __svnid__ = "$Id$" 37 13 __license__ = "Python" … … 39 15 __contributors__ = [ 40 16 "Stefano J. Attardi <http://attardi.org/>", 41 "limodou <http://www.donews.net/limodou/>" 17 "limodou <http://www.donews.net/limodou/>", 18 "Carlo C8E Miron" 42 19 ] 43 20 … … 47 24 ForeignKey, OneToOneField, ManyToManyField 48 25 from django.db.models.fields.generic import GenericRelation 26 from django.template import Template, Context 49 27 50 def generate_dot(app_label): 51 app = models.get_app(app_label) 28 dot_template = """ 29 digraph {{ name }} { 30 fontname = "Helvetica" 31 fontsize = 8 52 32 53 graph = []54 graph.append("digraph %s {" % ('"' + app.__name__ + '"'))55 graph.append(""" fontname = "Helvetica"56 fontsize = 857 58 33 node [ 59 34 fontname = "Helvetica" 60 35 fontsize = 8 61 shape = " record"36 shape = "plaintext" 62 37 ] 63 38 edge [ … … 65 40 fontsize = 8 66 41 ] 67 """) 68 for o in get_models(app): 69 graph.append(""" subgraph cluster_%(model)s { 70 shape = "record"; 71 label = "%(model)s"; 72 fontname = "Helvetica Bold"; 73 fontsize = 10; 74 labelfontcolor = "black"; 75 %(model)s [label = "{""" % {'model': o.__name__}) 42 43 {% for model in models %} 44 {{ model.name }} [label=< 45 <TABLE BGCOLOR="palegoldenrod" BORDER="0" CELLBORDER="0" CELLSPACING="0"> 46 <TR><TD COLSPAN="2" CELLPADDING="4" ALIGN="CENTER" BGCOLOR="olivedrab4" 47 ><FONT FACE="Helvetica Bold" COLOR="white" 48 >{{ model.name }}</FONT></TD></TR> 49 {% for field in model.fields %} 50 <TR><TD ALIGN="LEFT" BORDER="0" 51 ><FONT FACE="Helvetica Bold">{{ field.name }}</FONT 52 ></TD> 53 <TD ALIGN="LEFT">{{ field.type }}</TD></TR> 54 {% endfor %} 55 </TABLE> 56 >] 57 58 {% for relation in model.relations %} 59 {{ model.name }} -> {{ relation.target }} 60 [label="{{ relation.type }}"] {{ relation.arrows }}; 61 {% endfor %} 62 {% endfor %} 63 } 64 """ 65 66 def generate_dot(app_label): 67 app = models.get_app(app_label) 68 graph = Context({ 69 'name': '"%s"' % app.__name__, 70 'models': [] 71 }) 72 73 for appmodel in get_models(app): 74 model = { 75 'name': appmodel.__name__, 76 'fields': [], 77 'relations': [] 78 } 76 79 77 80 # model attributes 78 81 def add_attributes(): 79 graph.append("<%(model)s_%(field)s>%(field)s : %(related)s|" % \ 80 {'model': o.__name__, 'field': field.name, 81 'related': type(field).__name__}) 82 model['fields'].append({ 83 'name': field.name, 84 'type': type(field).__name__ 85 }) 82 86 83 for field in o._meta.fields:87 for field in appmodel._meta.fields: 84 88 add_attributes() 85 89 86 if o._meta.many_to_many:87 for field in o._meta.many_to_many:90 if appmodel._meta.many_to_many: 91 for field in appmodel._meta.many_to_many: 88 92 add_attributes() 89 93 90 graph.append(""" }"] [color="white" shape="record"];\n }\n""") 94 # relations 95 def add_relation(extras=""): 96 _rel = { 97 'target': field.rel.to.__name__, 98 'type': type(field).__name__, 99 'arrows': extras 100 } 101 if _rel not in model['relations']: 102 model['relations'].append(_rel) 91 103 92 # relations 93 rel = [] 94 def add_relation(extras=""): 95 _rel = """ %(model)s:%(model)s_%(field)s -> %(related)s 96 [label="%(relationship)s"] %(extras)s;\n""" % { 97 'model': o.__name__, 'field': field.name, 98 'related': field.rel.to.__name__, 99 'relationship': type(field).__name__, 100 'extras': extras} 101 if _rel not in rel: 102 rel.append(_rel) 103 104 for field in o._meta.fields: 104 for field in appmodel._meta.fields: 105 105 if isinstance(field, ForeignKey): 106 106 add_relation() … … 108 108 add_relation("[arrowhead=none arrowtail=none]") 109 109 110 if o._meta.many_to_many:111 for field in o._meta.many_to_many:110 if appmodel._meta.many_to_many: 111 for field in appmodel._meta.many_to_many: 112 112 if isinstance(field, ManyToManyField): 113 113 add_relation("[arrowhead=normal arrowtail=normal]") … … 115 115 add_relation( 116 116 '[style="dotted"] [arrowhead=normal arrowtail=normal]') 117 graph .append("".join(rel))118 119 graph.append('}')120 return "".join(graph)117 graph['models'].append(model) 118 119 t = Template(dot_template) 120 return t.render(graph) 121 121 122 122 if __name__ == "__main__": 123 123 import sys 124 app_label = sys.argv[1] 125 print generate_dot(app_label) 124 try: 125 app_label = sys.argv[1] 126 print generate_dot(app_label) 127 except IndexError: 128 print __doc__