用django来管理model

django 的 db orm ,因为有插件 south,用来做 db migration 那是相当好.

django准备

install

sudo pip install django south

config

django-admin.py startproject model

修改 settings.py ,配好db connect

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'monitor',
        'USER': 'monitor',
        'PASSWORD': 'monitor',
        'HOST': '127.0.0.1',
        'PORT': '5432',
    }
}

INSTALLED_APPS 里加入 south,和以后要建立的 monitor app

INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'south',
    'monitor',
)

init

python manage.py migrate
python manage.py startapp monitor

加入 models

#!/usr/bin/env python
* -*- coding: utf-8 -*-


from django.db import models
* Create your models here.


class MonConfigDetail(models.Model):
    id = models.IntegerField(primary_key=True)
    ip = models.TextField()
    mon_type = models.TextField()

    class Meta:
        db_table = 'mon_config_detail'

if __name__ == '__main__':
    pass

执行

python manage.py sql monitor

可以看到print出对应这个model的sql

BEGIN;
CREATE TABLE "mon_config_detail" (
    "id" integer NOT NULL PRIMARY KEY,
    "ip" text NOT NULL,
    "mon_type" text NOT NULL
)
;

COMMIT;

下面可以用 south了

south

init

python manage.py schemamigration monitor --initial

建立了一个迁移的初始版本

Creating migrations directory at '/home/bigzhu/Dropbox/djoin/monitor/model/monitor/migrations'...
Creating __init__.py in '/home/bigzhu/Dropbox/djoin/monitor/model/monitor/migrations'...
 + Added model monitor.MonConfigDetail
Created 0001_initial.py. You can now apply this migration with: ./manage.py migrate monitor

进行同步

manage.py migrate monitor

这时就把表建立到数据库了

修改了model

class MonConfigDetail(models.Model):
    id = models.IntegerField(primary_key=True)
    ip = models.TextField()
    mon_type = models.TextField()

    stat_date = models.DateTimeField(blank=True, null=True)
    create_date = models.DateTimeField(blank=True, null=True)

    class Meta:
        db_table = 'mon_config_detail'

生成版本

python manage.py schemamigration monitor --auto
 + Added field stat_date on monitor.MonConfigDetail
 + Added field create_date on monitor.MonConfigDetail
Created 0002_auto__add_field_monconfigdetail_stat_date__add_field_monconfigdetail_c.py. You can now apply this migration with: ./manage.py migrate monitor

应用

./manage.py migrate monitor

这时查看数据库,可以自到新加的几个字段已经上去了

回退版本

python manage.py migrate monitor 0001

可以看到数据库新加的两个字段没了.

不过用的时候要小心,可能会导致数据丢失.

ps

djaongo 没有 postgresql 的 json 类型

sudo pip install django-jsonfield
from django.db import models
import jsonfield

class MyModel(models.Model):
    the_json = jsonfield.JSONField()

然后发现无用!!!

只有自已动手了.

进入/usr/lib/python2.7/site-packages/django/db/backends/postgresql_psycopg2, 修改 creation.py data_types 加上 json 对应的类型JSONField

    data_types = {
        'AutoField':         'serial',
        'BinaryField':       'bytea',
        'BooleanField':      'boolean',
        'CharField':         'varchar(%(max_length)s)',
        'CommaSeparatedIntegerField': 'varchar(%(max_length)s)',
        'DateField':         'date',
        'DateTimeField':     'timestamp with time zone',
        'DecimalField':      'numeric(%(max_digits)s, %(decimal_places)s)',
        'FileField':         'varchar(%(max_length)s)',
        'FilePathField':     'varchar(%(max_length)s)',
        'FloatField':        'double precision',
        'IntegerField':      'integer',
        'BigIntegerField':   'bigint',
        'IPAddressField':    'inet',
        'GenericIPAddressField': 'inet',
        'NullBooleanField':  'boolean',
        'OneToOneField':     'integer',
        'PositiveIntegerField': 'integer CHECK ("%(column)s" >= 0)',
        'PositiveSmallIntegerField': 'smallint CHECK ("%(column)s" >= 0)',
        'SlugField':         'varchar(%(max_length)s)',
        'SmallIntegerField': 'smallint',
        'TextField':         'text',
        'JSONField':         'json',
        'TimeField':         'time',
    }

可实际上 django 并没有提供 JSONField 类型.

再改,进入/usr/lib/python2.7/site-packages/django/db/models/fields 修改__init__.py

加入

class JSONField(Field):
    description = _("Text")

    def get_internal_type(self):
        return "JSONField"

    def get_prep_value(self, value):
        if isinstance(value, six.string_types) or value is None:
            return value
        return smart_text(value)

    def formfield(self, **kwargs):
        defaults = {'widget': forms.Textarea}
        defaults.update(kwargs)
        return super(JSONField, self).formfield(**defaults)

其实就是把TextField改了名字.

model 改为

class MonConfigDetail(models.Model):
    id = models.IntegerField(primary_key=True)
    ip = models.TextField()
    mon_type = models.TextField()
    stat_date = models.DateTimeField(blank=True, null=True)
    create_date = models.DateTimeField(blank=True, null=True)
    warning_level = models.IntegerField()
    followers = models.JSONField()

    class Meta:
        db_table = 'mon_config_detail'
python manage.py sql monitor

成功了

BEGIN;
CREATE TABLE "mon_config_detail" (
    "id" integer NOT NULL PRIMARY KEY,
    "ip" text NOT NULL,
    "mon_type" text NOT NULL,
    "stat_date" timestamp with time zone,
    "create_date" timestamp with time zone,
    "warning_level" integer NOT NULL,
    "followers" json NOT NULL
)
;

COMMIT;