Login

A small script to rearranging the models generated from inspectdb command

Author:
m_tayseer
Posted:
November 18, 2008
Language:
Python
Version:
1.0
Score:
0 (after 0 ratings)

python manage.py inspectdb allows you to generate the models from a legacy database. The generated model classes are not arranged by dependencies. When the number of tables is big, it becomes really painful to rearrange by hand.

This small script should rearrange the models for you. It doesn't solve every problem with generated models, but it makes our the process easier

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
''' Usage
    python rearrange_models.py inspected_models.py ordered_models.py
'''

import re
from cStringIO import StringIO

class DjangoModelsArrangement:
    def __init__(self):
        self.output = StringIO()
        self.classes = {}
        self.already_written = set()

    def get_classes(self, input):
        # This regular expression will divide the input as
        # [file_header, class_declaration1, class_body1, class_declaration2, class_body2, ...]
        parsed_classes = re.split(r'(class\s+.*?\(models\.Model\):)', input)
        self.header = parsed_classes[0]
        return [i+j for i, j in zip(parsed_classes[1::2], parsed_classes[2::2])]
    
    def parse_class(self, class_def):
        lines = class_def.split('\n')
        class_decl, class_body = lines[0], lines[1:]
        class_name = re.findall(r'class\s+(.*?)\(models\.Model\):', class_decl)[0]
        referenced_set = set()
        for line in lines:
            if 'ForeignKey' in line:
                referenced_class = re.findall(r'ForeignKey\((.*?)(?:,|\))', line)[0]
                if referenced_class and referenced_class != "'self'":
                    referenced_set.add(referenced_class)
        self.classes[class_name] = (referenced_set, class_def)
    
    def write_class(self, class_):
        if class_ not in self.already_written:
            self.already_written.add(class_)
            referenced_set, class_def = self.classes[class_]
            if referenced_set:
                for referenced_class in referenced_set:
                    self.write_class(referenced_class)
            self.output.write(class_def)
            
                
    def arrange(self, source_file, dest_file):
        input = open(source_file).read()
        classes = self.get_classes(input)
        for class_ in classes:
            self.parse_class(class_)
        for class_ in self.classes:
            self.write_class(class_)
        output_data = self.output.getvalue()
        open(dest_file, 'w').write(self.header + output_data)
        
if __name__ == '__main__':
    import sys
    if len(sys.argv) != 3:
        print __doc__
        sys.exit(1)
    DjangoModelsArrangement().arrange(sys.argv[1], sys.argv[2])

More like this

  1. Template tag - list punctuation for a list of items by shapiromatron 10 months, 2 weeks ago
  2. JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 10 months, 3 weeks ago
  3. Serializer factory with Django Rest Framework by julio 1 year, 5 months ago
  4. Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 6 months ago
  5. Help text hyperlinks by sa2812 1 year, 7 months ago

Comments

m_tayseer (on November 24, 2008):

I fixed a bug where this script would raise a 'RuntimeError: maximum recursion depth exceeded'

#

Please login first before commenting.