Code

DjangoGraphviz: modelviz.2.py

File modelviz.2.py, 3.5 KB (added by QingFeng, 7 years ago)

Django Trunk GenericRelation Modify

Line 
1#!/usr/bin/env python
2"""Django model to DOT (Graphviz) converter
3by Antonio Cavedoni <antonio@cavedoni.org>
4
5Make sure your DJANGO_SETTINGS_MODULE is set to your project and call
6the script like this:
7
8$ python modelviz.py <app_label> > <filename>.dot
9"""
10
11__version__ = "0.6"
12__svnid__ = "$Id$"
13__license__ = "Python"
14__author__ = "Antonio Cavedoni <http://cavedoni.com/>"
15__contributors__ = [
16   "Stefano J. Attardi <http://attardi.org/>",
17   "limodou <http://www.donews.net/limodou/>",
18   "Carlo C8E Miron"
19   ]
20
21from django.db import models
22from django.db.models import get_models
23from django.db.models.fields.related import \
24    ForeignKey, OneToOneField, ManyToManyField
25try:
26        from django.db.models.fields.generic import GenericRelation
27except ImportError:
28        from django.contrib.contenttypes.generic import GenericRelation
29from django.template import Template, Context
30
31dot_template = """
32digraph {{ name }} {
33  fontname = "Helvetica"
34  fontsize = 8
35
36  node [
37    fontname = "Helvetica"
38    fontsize = 8
39    shape = "plaintext"
40  ]
41   edge [
42    fontname = "Helvetica"
43    fontsize = 8
44  ]
45
46  {% for model in models %}
47  {{ model.name }} [label=<
48    <TABLE BGCOLOR="palegoldenrod" BORDER="0" CELLBORDER="0" CELLSPACING="0">
49     <TR><TD COLSPAN="2" CELLPADDING="4" ALIGN="CENTER" BGCOLOR="olivedrab4"
50     ><FONT FACE="Helvetica Bold" COLOR="white"
51     >{{ model.name }}</FONT></TD></TR>
52     {% for field in model.fields %}
53     <TR><TD ALIGN="LEFT" BORDER="0"
54     ><FONT FACE="Helvetica Bold">{{ field.name }}</FONT
55     ></TD>
56     <TD ALIGN="LEFT">{{ field.type }}</TD></TR>
57     {% endfor %}
58    </TABLE>
59    >]
60   
61  {% for relation in model.relations %}
62  {{ model.name }} -> {{ relation.target }}
63    [label="{{ relation.type }}"] {{ relation.arrows }};
64  {% endfor %}
65  {% endfor %}
66}
67"""
68
69def generate_dot(app_label):
70   app = models.get_app(app_label)
71   graph = Context({
72      'name': '"%s"' % app.__name__, 
73      'models': []
74      })
75
76   for appmodel in get_models(app):
77      model = {
78         'name': appmodel.__name__,
79         'fields': [],
80         'relations': []
81         }
82
83      # model attributes
84      def add_attributes():
85         model['fields'].append({
86               'name': field.name,
87               'type': type(field).__name__
88               })
89
90      for field in appmodel._meta.fields:
91         add_attributes()
92         
93      if appmodel._meta.many_to_many:
94         for field in appmodel._meta.many_to_many:
95            add_attributes()
96
97      # relations
98      def add_relation(extras=""):
99         _rel = {
100            'target': field.rel.to.__name__,
101            'type': type(field).__name__,
102            'arrows': extras
103            }
104         if _rel not in model['relations']:
105            model['relations'].append(_rel)
106
107      for field in appmodel._meta.fields:
108         if isinstance(field, ForeignKey):
109            add_relation()
110         elif isinstance(field, OneToOneField):
111            add_relation("[arrowhead=none arrowtail=none]")
112
113      if appmodel._meta.many_to_many:
114         for field in appmodel._meta.many_to_many:
115            if isinstance(field, ManyToManyField):
116               add_relation("[arrowhead=normal arrowtail=normal]")
117            elif isinstance(field, GenericRelation):
118               add_relation(
119                  '[style="dotted"] [arrowhead=normal arrowtail=normal]')
120      graph['models'].append(model)
121   
122   t = Template(dot_template)
123   return t.render(graph)
124
125if __name__ == "__main__":
126   import sys
127   try:
128      app_label = sys.argv[1]
129      print generate_dot(app_label)
130   except IndexError:
131      print __doc__