manage.py inspectdb和enums

时间:2012-04-24 18:46:42

标签: mysql django inspectdb

A中有很多带有枚举的表和字段。

是否有能力像transit enum('yes','no') default 'no'一样检查MySQL的枚举?我看,默认情况下不起作用。

我的字符长度定义错误:ipaddr varchar(15) NOT NULL default '', - > ipaddr = models.CharField(max_length = 45)

1 个答案:

答案 0 :(得分:0)

似乎这个操作没有默认方法,或者我的问题对于awsering来说太愚蠢了。所以,我自己制作了自行车:) 它看起来像代码有效,但我没有很好地测试它。

#!/usr/bin/python

import re, MySQLdb
from MySQLdb import cursors
from settings import DATABASES

DB_SETUP = {
    'host':     DATABASES['default']['HOST'] or 'localhost',
    'user':     DATABASES['default']['USER'] or 'root',
    'passwd':   DATABASES['default']['PASSWORD'] or 'None',
    'db':       DATABASES['default']['NAME'] or 'mysql',
    'charset':  'utf8',
    }

db = MySQLdb.connect(cursorclass=cursors.DictCursor, **DB_SETUP)
cursor = db.cursor()

def max_len(str):
    return max([ len(i.strip().replace("'", '')) for i in str.split(',') ])

def get_enum_tuple(string):
    return tuple( (i.strip().replace("'", ''), i.strip().replace("'", '')) for i in string.split(',') )

patterns = {
    re.compile( r'enum\((?P<choices>[\'|\w|,*|\s*]+)\)', re.IGNORECASE):
        'models.CharField',
    re.compile( r'varchar\((?P<max_length>\d+)\)', re.IGNORECASE):
        'models.CharField',
    re.compile( r'char\((?P<max_length>\d+)\)', re.IGNORECASE):
        'models.CharField',
    re.compile( r'int\((?P<max_length>\d+)\)', re.IGNORECASE):
        'models.IntegerField',
    re.compile( r'tinyint\((?P<max_length>\d+)\)', re.IGNORECASE):
        'models.IntegerField',
    re.compile( r'datetime', re.IGNORECASE):
        'models.DateTimeField',
}

def table_classname(table):
    words = [ w.capitalize() for w in table.split('_') ]
    return ''.join(words)

cursor.execute('SHOW TABLES')
for table in [ i.values()[0] for i in cursor.fetchall() ]:
    cursor.execute('DESCRIBE `%s`' % table)

    class_model = []
    for row in cursor.fetchall():
        args = []
        if row['Null'] == 'YES':        args.append('blank=True')
        if row['Default']:              args.append("default='%s'" % row['Default'])
        if row['Key'] == 'PRI':         args.append('primary_key=True')
        if row['Key'] == 'UNI':         args.append('unique=True')

        if '-' in row['Field']:
            args.append("db_column='%s'" % row['Field'])
            row['Field'] = row['Field'].replace('-', '_')

        field_type = None
        for pat in patterns:
            m = pat.match(row['Type'])
            if m:
                d = m.groupdict()
                if 'choices' in d:
                    args.append('max_length=%s' % max_len(d['choices']))
                    args.append('choices=%s' % str(get_enum_tuple(d['choices'])) )
                    del d['choices']

                if d:
                    for k in d:
                        args.append( '%s=%s' % (k, d[k]) )

                field_type = patterns[pat]
                break

        args = ', '.join(args)
        class_model.append( '{field} = {field_type}({args})'.format(field=row['Field'], field_type=field_type, args=args) )

    print 'class %s(models.Model):' % table_classname(table)
    for s in class_model:
        print '\t%s' % s

    print '\n\tclass Meta:'
    print "\t\tdb_table = '%s'\n" % table