擼了個 django 數(shù)據(jù)遷移工具 django-supertube
支持字段映射和動態(tài)字段轉(zhuǎn)化。 歡迎 star,issue
https://github.com/FingerLiu/django-supertube
起因
最近參與了公司系統(tǒng)的重構(gòu),重構(gòu)基本完成后,由于數(shù)據(jù)庫表結(jié)構(gòu)變化很大,很多小組都需要數(shù)據(jù)遷移。如果都寫 sql 的話,要做很多重復(fù)的工作。于是去搜了下 django 有沒有相關(guān)的工具,很遺憾沒有搜到,于是自己擼了這個數(shù)據(jù)遷移的輪子。
主要功能
A powerful django migration tool to migrate from latency database to new databse using awesome django ORM
使用 django 強(qiáng)大的 ORM 系統(tǒng)靈活的進(jìn)行數(shù)據(jù)遷移工作。
目前包含以下功能點:
- 支持相同字段自動映射
- 批量寫入
- 支持修改字段映射
- 支持通過調(diào)用函數(shù)的方式
- 自動修復(fù) postgres sequence
- 實時進(jìn)度提醒
- 數(shù)據(jù)量大時支持并行執(zhí)行(開發(fā)中)
django-supertube
A powerful django migration tool to migrate from latency database to new databse using awesome django ORM
例子
settings.py
DATABASES = {
'default': config('DATABASE_URL', cast=db_url),
'latency': config('LATENCY_DATABASE_URL', cast=db_url)
}
management/commands/mig_01_user.py
from django.utils import timezone
from si.tools.supertube import SuperTube, TubeSet
"""
class LatencyUser:
email
password
age
class User:
email
age
username
password
is_admin
create_datetime
例子從 latency 數(shù)據(jù)庫的 LatencyUser 取數(shù)據(jù)遷移到 default 數(shù)據(jù)庫的 User 中:
- 新加 username 字段,數(shù)據(jù)值從原 email 字段取
- 修改 age 字段變?yōu)樵瓉淼?age+1
- 新加 create_datetime 字段
- 新加 is_admin 字段,默認(rèn)值為 False
"""
class Command(BaseCommand):
def handle(self, *args, **options):
kwargs = {
'mapping': {
'username': 'email',
'age': lambda obj: obj.age + 1,
'create_datetime': timezone.now()},
'defaults': {'is_admin': False}
'source_db': 'whistler'
}
st = SuperTube(LatencyUser, User, **kwargs)
st.run(stop_on_error=True)
遷移工具 SuperTube 和 TubeSet 更多說明和例子參考這個文檔
一個為 latency 中的舊數(shù)據(jù)建表的例子:
class Order(models.Model):
sn = models.CharField(u'領(lǐng)用單編號', max_length=100)
created = models.DateTimeField(u'創(chuàng)建時間', auto_now_add=True)
apply_qty = models.IntegerField(u'計劃領(lǐng)用數(shù)量', blank=True, null=True)
# TODO 1 將原 model 中的外鍵字段名改為 原字段名+_id ,類型改為 IntegerField
# batch = models.ForeignKey('stock.Batch', blank=True, null=True)
batch_id = models.IntegerField('stock.Batch', blank=True, null=True)
purpose = models.PositiveIntegerField(u'領(lǐng)用用途', choices=PURPOSES, blank=True, null=True)
# platform = models.ForeignKey('si.Platform', blank=True, null=True, related_name='+')
platform_id = models.IntegerField('si.Platform', blank=True, null=True)
def __unicode__(self):
return self.sn
class Meta:
verbose_name = u'Order'
# TODO 2 注釋掉原表中的 unique_together
# unique_together = (
# ('platform', 'request_id'),
# ('platform', 'outer_id'),
# )
# TODO 3 managed 設(shè)為 False
managed = False
# TODO 4 指定 db table
db_table = 'cardbox_applyvoucher'