mirror of
https://expo.survex.com/repositories/troggle/.git
synced 2025-12-14 21:57:09 +00:00
modelviz added
This commit is contained in:
201
modelviz.py
Executable file
201
modelviz.py
Executable file
@@ -0,0 +1,201 @@
|
||||
#!/usr/bin/env python
|
||||
"""Django model to DOT (Graphviz) converter
|
||||
by Antonio Cavedoni <antonio@cavedoni.org>
|
||||
|
||||
Make sure your DJANGO_SETTINGS_MODULE is set to your project or
|
||||
place this script in the same directory of the project and call
|
||||
the script like this:
|
||||
|
||||
$ python modelviz.py [-h] [-d] <app_label> ... <app_label> > <filename>.dot
|
||||
$ dot <filename>.dot -Tpng -o <filename>.png
|
||||
|
||||
options:
|
||||
-h, --help
|
||||
show this help message and exit.
|
||||
|
||||
-d, --disable_fields
|
||||
don't show the class member fields.
|
||||
"""
|
||||
__version__ = "0.8"
|
||||
__svnid__ = "$Id: modelviz.py 78 2007-07-15 19:04:47Z verbosus $"
|
||||
__license__ = "Python"
|
||||
__author__ = "Antonio Cavedoni <http://cavedoni.com/>"
|
||||
__contributors__ = [
|
||||
"Stefano J. Attardi <http://attardi.org/>",
|
||||
"limodou <http://www.donews.net/limodou/>",
|
||||
"Carlo C8E Miron",
|
||||
"Andre Campos <cahenan@gmail.com>",
|
||||
"Justin Findlay <jfindlay@gmail.com>",
|
||||
]
|
||||
|
||||
import getopt, sys
|
||||
|
||||
from django.core.management import setup_environ
|
||||
|
||||
try:
|
||||
import settings
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
setup_environ(settings)
|
||||
|
||||
from django.template import Template, Context
|
||||
from django.db import models
|
||||
from django.db.models import get_models
|
||||
from django.db.models.fields.related import \
|
||||
ForeignKey, OneToOneField, ManyToManyField
|
||||
|
||||
try:
|
||||
from django.db.models.fields.generic import GenericRelation
|
||||
except ImportError:
|
||||
from django.contrib.contenttypes.generic import GenericRelation
|
||||
|
||||
head_template = """
|
||||
digraph name {
|
||||
fontname = "Helvetica"
|
||||
fontsize = 8
|
||||
|
||||
node [
|
||||
fontname = "Helvetica"
|
||||
fontsize = 8
|
||||
shape = "plaintext"
|
||||
]
|
||||
edge [
|
||||
fontname = "Helvetica"
|
||||
fontsize = 8
|
||||
]
|
||||
|
||||
"""
|
||||
|
||||
body_template = """
|
||||
{% for model in models %}
|
||||
{% for relation in model.relations %}
|
||||
{{ relation.target }} [label=<
|
||||
<TABLE BGCOLOR="palegoldenrod" BORDER="0" CELLBORDER="0" CELLSPACING="0">
|
||||
<TR><TD COLSPAN="2" CELLPADDING="4" ALIGN="CENTER" BGCOLOR="olivedrab4"
|
||||
><FONT FACE="Helvetica Bold" COLOR="white"
|
||||
>{{ relation.target }}</FONT></TD></TR>
|
||||
</TABLE>
|
||||
>]
|
||||
{{ model.name }} -> {{ relation.target }}
|
||||
[label="{{ relation.name }}"] {{ relation.arrows }};
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
|
||||
{% for model in models %}
|
||||
{{ model.name }} [label=<
|
||||
<TABLE BGCOLOR="palegoldenrod" BORDER="0" CELLBORDER="0" CELLSPACING="0">
|
||||
<TR><TD COLSPAN="2" CELLPADDING="4" ALIGN="CENTER" BGCOLOR="olivedrab4"
|
||||
><FONT FACE="Helvetica Bold" COLOR="white"
|
||||
>{{ model.name }}</FONT></TD></TR>
|
||||
|
||||
{% if not disable_fields %}
|
||||
{% for field in model.fields %}
|
||||
<TR><TD ALIGN="LEFT" BORDER="0"
|
||||
><FONT {% if field.blank %}COLOR="#7B7B7B" {% endif %}FACE="Helvetica Bold">{{ field.name }}</FONT
|
||||
></TD>
|
||||
<TD ALIGN="LEFT"
|
||||
><FONT {% if field.blank %}COLOR="#7B7B7B" {% endif %}FACE="Helvetica Bold">{{ field.type }}</FONT
|
||||
></TD></TR>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</TABLE>
|
||||
>]
|
||||
{% endfor %}
|
||||
"""
|
||||
|
||||
tail_template = """
|
||||
}
|
||||
"""
|
||||
|
||||
def generate_dot(app_labels, **kwargs):
|
||||
disable_fields = kwargs.get('disable_fields', False)
|
||||
|
||||
dot = head_template
|
||||
|
||||
for app_label in app_labels:
|
||||
app = models.get_app(app_label)
|
||||
graph = Context({
|
||||
'name': '"%s"' % app.__name__,
|
||||
'disable_fields': disable_fields,
|
||||
'models': []
|
||||
})
|
||||
|
||||
for appmodel in get_models(app):
|
||||
model = {
|
||||
'name': appmodel.__name__,
|
||||
'fields': [],
|
||||
'relations': []
|
||||
}
|
||||
|
||||
# model attributes
|
||||
def add_attributes():
|
||||
model['fields'].append({
|
||||
'name': field.name,
|
||||
'type': type(field).__name__,
|
||||
'blank': field.blank
|
||||
})
|
||||
|
||||
for field in appmodel._meta.fields:
|
||||
add_attributes()
|
||||
|
||||
if appmodel._meta.many_to_many:
|
||||
for field in appmodel._meta.many_to_many:
|
||||
add_attributes()
|
||||
|
||||
# relations
|
||||
def add_relation(extras=""):
|
||||
_rel = {
|
||||
'target': field.rel.to.__name__,
|
||||
'type': type(field).__name__,
|
||||
'name': field.name,
|
||||
'arrows': extras
|
||||
}
|
||||
if _rel not in model['relations']:
|
||||
model['relations'].append(_rel)
|
||||
|
||||
for field in appmodel._meta.fields:
|
||||
if isinstance(field, ForeignKey):
|
||||
add_relation()
|
||||
elif isinstance(field, OneToOneField):
|
||||
add_relation("[arrowhead=none arrowtail=none]")
|
||||
|
||||
if appmodel._meta.many_to_many:
|
||||
for field in appmodel._meta.many_to_many:
|
||||
if isinstance(field, ManyToManyField):
|
||||
add_relation("[arrowhead=normal arrowtail=normal]")
|
||||
elif isinstance(field, GenericRelation):
|
||||
add_relation(
|
||||
'[style="dotted"] [arrowhead=normal arrowtail=normal]')
|
||||
graph['models'].append(model)
|
||||
|
||||
t = Template(body_template)
|
||||
dot += '\n' + t.render(graph)
|
||||
|
||||
dot += '\n' + tail_template
|
||||
|
||||
return dot
|
||||
|
||||
def main():
|
||||
try:
|
||||
opts, args = getopt.getopt(sys.argv[1:], "hd",
|
||||
["help", "disable_fields"])
|
||||
except getopt.GetoptError, error:
|
||||
print __doc__
|
||||
sys.exit(error)
|
||||
else:
|
||||
if not args:
|
||||
print __doc__
|
||||
sys.exit()
|
||||
|
||||
kwargs = {}
|
||||
for opt, arg in opts:
|
||||
if opt in ("-h", "--help"):
|
||||
print __doc__
|
||||
sys.exit()
|
||||
if opt in ("-d", "--disable_fields"):
|
||||
kwargs['disable_fields'] = True
|
||||
print generate_dot(args, **kwargs)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user