Changeset 73

Show
Ignore:
Timestamp:
06/21/07 17:32:52 (19 months ago)
Author:
verbosus
Message:

Applied patch from Andre Henrique Campos, now support -h and -d options, accepts more than one app at a time, properly supports GenericRelation? fields. Thanks, Andre!

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • django/trunk/utils/modelviz.py

    r51 r73  
    33by Antonio Cavedoni <antonio@cavedoni.org> 
    44 
    5 Make sure your DJANGO_SETTINGS_MODULE is set to your project and call  
     5Make sure your DJANGO_SETTINGS_MODULE is set to your project or 
     6place this script in the same directory of the project and call 
    67the script like this: 
    78 
    8 $ python modelviz.py <app_label> > <filename>.dot 
     9$ python modelviz.py [-h] [-d] <app_label> ... <app_label> > <filename>.dot 
     10$ dot <filename>.dot -Tpng -o <filename>.png 
     11 
     12options: 
     13    -h, --help 
     14    show this help message and exit. 
     15 
     16    -d, --disable_fields 
     17    don't show the class member fields. 
    918""" 
    10  
    11 __version__ = "0.6" 
     19__version__ = "0.7" 
    1220__svnid__ = "$Id$" 
    1321__license__ = "Python" 
     
    1624   "Stefano J. Attardi <http://attardi.org/>", 
    1725   "limodou <http://www.donews.net/limodou/>", 
    18    "Carlo C8E Miron" 
     26   "Carlo C8E Miron", 
     27   "Andre Campos <cahenan@gmail.com>", 
    1928   ] 
    2029 
     30import getopt, sys 
     31 
     32from django.core.management import setup_environ 
     33 
     34try: 
     35    import settings 
     36except ImportError: 
     37    pass 
     38else: 
     39    setup_environ(settings) 
     40 
     41from django.template import Template, Context 
    2142from django.db import models 
    2243from django.db.models import get_models 
    2344from django.db.models.fields.related import \ 
    2445    ForeignKey, OneToOneField, ManyToManyField 
    25 from django.db.models.fields.generic import GenericRelation 
    26 from django.template import Template, Context 
    2746 
    28 dot_template = """ 
    29 digraph {{ name }} { 
     47try: 
     48    from django.db.models.fields.generic import GenericRelation 
     49except ImportError: 
     50    from django.contrib.contenttypes.generic import GenericRelation 
     51 
     52head_template = """ 
     53digraph name { 
    3054  fontname = "Helvetica" 
    3155  fontsize = 8 
     
    4165  ] 
    4266 
     67""" 
     68 
     69body_template = """ 
    4370  {% for model in models %} 
    44   {{ model.name }} [label=< 
     71    {% for relation in model.relations %} 
     72    {{ relation.target }} [label=< 
     73        <TABLE BGCOLOR="palegoldenrod" BORDER="0" CELLBORDER="0" CELLSPACING="0"> 
     74        <TR><TD COLSPAN="2" CELLPADDING="4" ALIGN="CENTER" BGCOLOR="olivedrab4" 
     75        ><FONT FACE="Helvetica Bold" COLOR="white" 
     76        >{{ relation.target }}</FONT></TD></TR> 
     77        </TABLE> 
     78        >] 
     79    {{ model.name }} -> {{ relation.target }} 
     80    [label="{{ relation.name }}"] {{ relation.arrows }}; 
     81    {% endfor %} 
     82  {% endfor %} 
     83 
     84  {% for model in models %} 
     85    {{ model.name }} [label=< 
    4586    <TABLE BGCOLOR="palegoldenrod" BORDER="0" CELLBORDER="0" CELLSPACING="0"> 
    4687     <TR><TD COLSPAN="2" CELLPADDING="4" ALIGN="CENTER" BGCOLOR="olivedrab4" 
    4788     ><FONT FACE="Helvetica Bold" COLOR="white" 
    4889     >{{ 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 %} 
     90 
     91    {% if not disable_fields %} 
     92        {% for field in model.fields %} 
     93        <TR><TD ALIGN="LEFT" BORDER="0" 
     94        ><FONT FACE="Helvetica Bold">{{ field.name }}</FONT 
     95        ></TD> 
     96        <TD ALIGN="LEFT">{{ field.type }}</TD></TR> 
     97        {% endfor %} 
     98    {% endif %} 
    5599    </TABLE> 
    56100    >] 
    57     
    58   {% for relation in model.relations %} 
    59   {{ model.name }} -> {{ relation.target }}  
    60     [label="{{ relation.type }}"] {{ relation.arrows }}; 
    61101  {% endfor %} 
    62   {% endfor %} 
     102""" 
     103 
     104tail_template = """ 
    63105} 
    64106""" 
    65107 
    66 def generate_dot(app_label): 
    67    app = models.get_app(app_label) 
    68    graph = Context({ 
    69       'name': '"%s"' % app.__name__,  
    70       'models': [] 
    71       }) 
     108def generate_dot(app_labels, **kwargs): 
     109    disable_fields = kwargs.get('disable_fields', False) 
    72110 
    73    for appmodel in get_models(app): 
    74       model = { 
    75          'name': appmodel.__name__, 
    76          'fields': [], 
    77          'relations': [] 
    78          } 
     111    dot = head_template 
    79112 
    80       # model attributes 
    81       def add_attributes(): 
    82          model['fields'].append({ 
    83                'name': field.name, 
    84                'type': type(field).__name__ 
    85                }) 
     113    for app_label in app_labels: 
     114        app = models.get_app(app_label) 
     115        graph = Context({ 
     116            'name': '"%s"' % app.__name__, 
     117            'disable_fields': disable_fields, 
     118            'models': [] 
     119            }) 
    86120 
    87       for field in appmodel._meta.fields: 
    88          add_attributes() 
    89           
    90       if appmodel._meta.many_to_many: 
    91          for field in appmodel._meta.many_to_many: 
    92             add_attributes() 
     121        for appmodel in get_models(app): 
     122            model = { 
     123                'name': appmodel.__name__, 
     124                'fields': [], 
     125                'relations': [] 
     126                } 
    93127 
    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) 
     128            # model attributes 
     129            def add_attributes(): 
     130                model['fields'].append({ 
     131                    'name': field.name, 
     132                    'type': type(field).__name__ 
     133                    }) 
    103134 
    104       for field in appmodel._meta.fields: 
    105          if isinstance(field, ForeignKey): 
    106             add_relation() 
    107          elif isinstance(field, OneToOneField): 
    108             add_relation("[arrowhead=none arrowtail=none]") 
     135            for field in appmodel._meta.fields: 
     136                add_attributes() 
    109137 
    110       if appmodel._meta.many_to_many: 
    111          for field in appmodel._meta.many_to_many: 
    112             if isinstance(field, ManyToManyField): 
    113                add_relation("[arrowhead=normal arrowtail=normal]") 
    114             elif isinstance(field, GenericRelation): 
    115                add_relation( 
    116                   '[style="dotted"] [arrowhead=normal arrowtail=normal]') 
    117       graph['models'].append(model) 
    118     
    119    t = Template(dot_template) 
    120    return t.render(graph) 
     138            if appmodel._meta.many_to_many: 
     139                for field in appmodel._meta.many_to_many: 
     140                    add_attributes() 
     141 
     142            # relations 
     143            def add_relation(extras=""): 
     144                _rel = { 
     145                    'target': field.rel.to.__name__, 
     146                    'type': type(field).__name__, 
     147                    'name': field.name, 
     148                    'arrows': extras 
     149                    } 
     150                if _rel not in model['relations']: 
     151                    model['relations'].append(_rel) 
     152 
     153            for field in appmodel._meta.fields: 
     154                if isinstance(field, ForeignKey): 
     155                    add_relation() 
     156                elif isinstance(field, OneToOneField): 
     157                    add_relation("[arrowhead=none arrowtail=none]") 
     158 
     159            if appmodel._meta.many_to_many: 
     160                for field in appmodel._meta.many_to_many: 
     161                    if isinstance(field, ManyToManyField): 
     162                        add_relation("[arrowhead=normal arrowtail=normal]") 
     163                    elif isinstance(field, GenericRelation): 
     164                        add_relation( 
     165                            '[style="dotted"] [arrowhead=normal arrowtail=normal]') 
     166            graph['models'].append(model) 
     167 
     168        t = Template(body_template) 
     169        dot += '\n' + t.render(graph) 
     170 
     171    dot += '\n' + tail_template 
     172 
     173    return dot 
     174 
     175def main(): 
     176    try: 
     177        opts, args = getopt.getopt(sys.argv[1:], "hd", 
     178                    ["help", "disable_fields"]) 
     179    except getopt.GetoptError, error: 
     180        print __doc__ 
     181        sys.exit(error) 
     182    else: 
     183        if not args: 
     184            print __doc__ 
     185            sys.exit() 
     186 
     187    kwargs = {} 
     188    for opt, arg in opts: 
     189        if opt in ("-h", "--help"): 
     190            print __doc__ 
     191            sys.exit() 
     192        if opt in ("-d", "--disable_fields"): 
     193            kwargs['disable_fields'] = True 
     194    print generate_dot(args, **kwargs) 
    121195 
    122196if __name__ == "__main__": 
    123    import sys 
    124    try: 
    125       app_label = sys.argv[1] 
    126       print generate_dot(app_label) 
    127    except IndexError: 
    128       print __doc__ 
     197    main()