强大的Django模型层插件:south详解
2017-03-16 18:36
525 查看
一、下载与安装
south安装包下载地址:https://bitbucket.org/andrewgodwin/south/
south文档:http://south.readthedocs.org/en/latest/
二、south简介
Django 的第三方 app South 就是专门做数据库表结构自动迁移工作,Jacob Kaplan-Moss 曾做过一次调查,South 名列最受欢迎的第三方 app。事实上,它现在已经俨然成为 Django 事实上的数据库表迁移标准,很多第三方 app 都会带 South migrations 脚本。
三、回顾syncdb
syncdb是db synchronization的缩写,意思是数据库同步。
syncdb 命令是同步你的模型到数据库的一个简单方法。 它会根据 INSTALLED_APPS 里设置的app来检查数据库, 如果表不存在,它就会创建它。 需要注意的是, syncdb 并不能将模型的修改或删除同步到数据库;如果你修改或删除了一个模型,并想把它提交到数据库,syncdb并不会做出任何处理。
如果你再次运行 python manage.py syncdb ,什么也没发生,因为你没有添加新的模型或者添加新的app。因此,运行python manage.py syncdb总是安全的,因为它不会重复执行SQL语句。
知识总结:迁移( migrations?)
四、为什么用south
对于二、三两点,可知syncdb的不足,如果更改了models,如添加一列等此时syncdb就没有用武之地了,如果硬手工修改表结构不仅容易出错,又不安全,并非权宜之计,而south却能很好的解决该问题。
south特性:
(1)、自动迁移:south可自动检测你的Models.py文件的改变,自动写入migrations去匹配你所做的改变。
(2)、数据库独立性:完全与数据库无关的,支持五个不同的数据库后端。这样就无需再关注于数据库方向,而专注与django。
(3)、app艺术:south依赖app,south本身也是django的第三方app,再在使用的时候单独作用于每个app下,进行迁移,同步。
(4)、VCS处理:south也能处理如果别人提交迁移到相同的应用程序作为你和他们冲突。
你写的迁移(migrations),它告诉south如何从一个版本升级到下一个,和通过串接在一起你可以移动这些迁移向前(或向后)通过历史数据库的模式。south也能创建新的model
五、快速指南
1、安装完South之后,要在django项目中使用South,先要将South作为一个App导入项目,所以设置INSTALL_APP添加south 第一次使用South。
2、manage.py syncdb 用来创建south_migrationhistory表。
3、manage.py convert_to_south youappname #在youappname目录下面创建migrations目录以及第一次迁移需要的0001_initial.py文件
4、如果改变了model里的内容,./manage.py schemamigration youappname --auto #检测对models的更改
manage.py migrate youappnam #将更改反应到数据库(如果出现表已存在的错误,后面加 --fake)
如果第一次使用:
1、./manage.py schemamigration youappname --initial # youappname目录下面创建一个migrations的子目录(注意!!就算有多个app,也只要initial一个就可以)
2、./manage.py syncdb #初始化数据表等
#以后每次对models更改后,可以运行以下两条命令同步到数据库
3、./manage.py schemamigration youappname --auto #检测对models的更改
4、./manage.py migrate youappnam #将更改反应到数据库(如果出现表已存在的错误,后面加 --fake)
推荐教程:
http://codinn.com/people/brant/notes/110932/ http://a280606790.iteye.com/blog/1107657
六、深入基础教程(首度使用)
1、新建models
新建southtut app,然后定义models如下:
然后使用 syncdb 为它创建一个迁移。
2、第一个迁移
south创建迁移有以下两种方式:自动和手动,对于新手来说推荐两种自动方式:--auto和--initial.
我们使用manage.py schemamigration app_name时候:(schema migration:模式 迁移,简化为schemamigration)
--auto:作用于旧的(已经存在)的迁移(migration),对一些改变做出迁移工作,如增加字段等。
--initial:针对新的(尚未存在)的迁移,将创建表和索引对应到app 的models下。这是当你定义好model后的初步使用,如同syncdb一样。
接下来开始创建第一个迁移
完了之后,在项目目录结构中可见以下改变:
当然也创建了该model:southtut.Knight
那么接下来就应用新的迁移,注意如果已经存在该model则使用 --fake
3、应用改变
这里添加一个字段,要把给字段给同步上去。
那么接下来就是同步了,此时分两个步骤:
(1)、创建迁移:manage.py schemamigration southtut --auto
(2)、应用:manage.py migrate southtut
完成之后,则发现已经添加了该字段
七、深入基础教程(迁移使用)
1、基本流程
对于已经之前已经存在的model,如果我们使用south则不能使用上面的步骤。比如说,我有一个名为other的app下model早已建立并且同步至数据库,那么我想要用south,那么就要作如下处理了。
ok,我要用这个,且在model里动了手脚。
那么使用south如下:
(1)、创建迁移:(--auto)
(2)、应用:
流程给出了,但是为什么省略输出的部分呢,因为这里涉及到一个知识点,就是Defaults:
2、defaults
对于上面southtut app model存在BooleanField,则该字段默认的default=False,然而对于其他字段,可能没有定义默认字段,如果列为空,既null=True,那么新生成的列就没有威胁了,否则就必须给出默认值,因为对于已经存在数据的model,新的字段不可能没有值。一些数据库后端将让你添加列,如果表是空的,而有些会拒绝彻底。
针对这种情况,south将会给出选择并执行
3、Uniques
还有一点重要的是unique属性
然后再manage.py migrate southtut 就ok了。
4、ManyToMany fields
south能够检测多对多字段,South will create the table the ManyToMany represents, and when you remove the field, the table will be deleted.
一、迁移清单
列出某个app下的迁移清单,或整个django项目的迁移清单,相当于列出其历史记录,这时要用到
显示如下。注意带*的为已经应用到了 ,()表示尚未应用到的。
二、数据迁移
第一节所涉及的是模式迁移,涉及表、字段、索引的添加和删除;另一种迁移就是数据迁移。
数据迁移是用来改变你的数据库中存储的数据匹配一个新的模式,或特性。
例如,如果你一直以纯文本形式保存密码,现在你需要以利用salt对密码进行散列 的形式,这样就涉及到数据的迁移以适应新的模式。可能有以下三个步骤(每个步骤对应一个迁移):
(1)、创建两列:password_salt 和password_hash (a schema migration).
(2)、使用旧密码的列的内容,计算每个用户的密码后应用到新的列(a data migration)
(3)、移除旧的密码列(a schema migration).
假设有用户:Jack,密码:admin123.如果以文本的形式肯定不安全了,那么现在就利用salt对密码进行散列。
接下来就是创建模式迁移将会创建两列:
那么接下来就是创建数据迁移了,
打开 0014_hash_passwords.py 文件 发现如下,我们还需要手写forwards、backwards方法
更改如下:
注意这里的orm.User,对象关系映射(Object Relational Mapping) 这里关系到其迁移的model,如User model。如果用数据迁移中使用其他app的model则用orm['contenttypes.ContentType']. Models
If you want to access models from other apps in your data migration, use a syntax likeorm['contenttypes.ContentType']. Models will be available if you can somehow get to them via ForeignKey or ManyToMany traversal from your app’s models; if you want to freeze other models, simply pass--freeze appname on the datamigration command line.
最后在backwards()方法中引发错误,因为这个过程本质上是不可逆转的。就是说只能向前迁移,不能向后。
最后步骤:删除password字段,启动迁移
接下来就是应用这3个迁移:
接下来验证一下:
<script>window._bd_share_config={"common":{"bdSnsKey":{},"bdText":"","bdMini":"2","bdMiniList":false,"bdPic":"","bdStyle":"0","bdSize":"16"},"share":{}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)];</script>
阅读(7443) | 评论(0) | 转发(0) |
0
上一篇:python中几个内置函数的用法
下一篇:python图像处理库PIL介绍
相关热门文章
ASP使用内置对象前不必创建...
bootStrap中Tab页签切换
京东SSO单点登陆实现分析...
WebRTC学习笔记
强大的http调试工具charles用...
linux dhcp peizhi roc
关于Unix文件的软链接
求教这个命令什么意思,我是新...
sed -e "/grep/d" 是什么意思...
谁能够帮我解决LINUX 2.6 10...
给主人留下些什么吧!~~
评论热议
south安装包下载地址:https://bitbucket.org/andrewgodwin/south/
south文档:http://south.readthedocs.org/en/latest/
二、south简介
Django 的第三方 app South 就是专门做数据库表结构自动迁移工作,Jacob Kaplan-Moss 曾做过一次调查,South 名列最受欢迎的第三方 app。事实上,它现在已经俨然成为 Django 事实上的数据库表迁移标准,很多第三方 app 都会带 South migrations 脚本。
三、回顾syncdb
syncdb是db synchronization的缩写,意思是数据库同步。
syncdb 命令是同步你的模型到数据库的一个简单方法。 它会根据 INSTALLED_APPS 里设置的app来检查数据库, 如果表不存在,它就会创建它。 需要注意的是, syncdb 并不能将模型的修改或删除同步到数据库;如果你修改或删除了一个模型,并想把它提交到数据库,syncdb并不会做出任何处理。
如果你再次运行 python manage.py syncdb ,什么也没发生,因为你没有添加新的模型或者添加新的app。因此,运行python manage.py syncdb总是安全的,因为它不会重复执行SQL语句。
知识总结:迁移( migrations?)
四、为什么用south
对于二、三两点,可知syncdb的不足,如果更改了models,如添加一列等此时syncdb就没有用武之地了,如果硬手工修改表结构不仅容易出错,又不安全,并非权宜之计,而south却能很好的解决该问题。
south特性:
(1)、自动迁移:south可自动检测你的Models.py文件的改变,自动写入migrations去匹配你所做的改变。
(2)、数据库独立性:完全与数据库无关的,支持五个不同的数据库后端。这样就无需再关注于数据库方向,而专注与django。
(3)、app艺术:south依赖app,south本身也是django的第三方app,再在使用的时候单独作用于每个app下,进行迁移,同步。
(4)、VCS处理:south也能处理如果别人提交迁移到相同的应用程序作为你和他们冲突。
你写的迁移(migrations),它告诉south如何从一个版本升级到下一个,和通过串接在一起你可以移动这些迁移向前(或向后)通过历史数据库的模式。south也能创建新的model
五、快速指南
1、安装完South之后,要在django项目中使用South,先要将South作为一个App导入项目,所以设置INSTALL_APP添加south 第一次使用South。
2、manage.py syncdb 用来创建south_migrationhistory表。
3、manage.py convert_to_south youappname #在youappname目录下面创建migrations目录以及第一次迁移需要的0001_initial.py文件
4、如果改变了model里的内容,./manage.py schemamigration youappname --auto #检测对models的更改
manage.py migrate youappnam #将更改反应到数据库(如果出现表已存在的错误,后面加 --fake)
如果第一次使用:
1、./manage.py schemamigration youappname --initial # youappname目录下面创建一个migrations的子目录(注意!!就算有多个app,也只要initial一个就可以)
2、./manage.py syncdb #初始化数据表等
#以后每次对models更改后,可以运行以下两条命令同步到数据库
3、./manage.py schemamigration youappname --auto #检测对models的更改
4、./manage.py migrate youappnam #将更改反应到数据库(如果出现表已存在的错误,后面加 --fake)
推荐教程:
http://codinn.com/people/brant/notes/110932/ http://a280606790.iteye.com/blog/1107657
六、深入基础教程(首度使用)
1、新建models
新建southtut app,然后定义models如下:
class Knight(models.Model): name = models.CharField(max_length=100) of_the_round_table = models.BooleanField()
然后使用 syncdb 为它创建一个迁移。
2、第一个迁移
south创建迁移有以下两种方式:自动和手动,对于新手来说推荐两种自动方式:--auto和--initial.
我们使用manage.py schemamigration app_name时候:(schema migration:模式 迁移,简化为schemamigration)
--auto:作用于旧的(已经存在)的迁移(migration),对一些改变做出迁移工作,如增加字段等。
--initial:针对新的(尚未存在)的迁移,将创建表和索引对应到app 的models下。这是当你定义好model后的初步使用,如同syncdb一样。
接下来开始创建第一个迁移
E:\project\demo>manage.py schemamigration southtut --initial Creating migrations directory at 'E:\project\demo\southtut\migrations'...#创建迁移目录migrations Creating __init__.py in 'E:\project\demo\southtut\migrations'...#创建__init__.py + Added model southtut.Knight #增加model Created 0001_initial.py. You can now apply this migration with: ./manage.py migrate southtut#创建版本控制
完了之后,在项目目录结构中可见以下改变:
当然也创建了该model:southtut.Knight
那么接下来就应用新的迁移,注意如果已经存在该model则使用 --fake
E:\project\demo>manage.py migrate southtut --fake #启动 Running migrations for southtut: #启动该app下的migrations - Migrating forwards to 0001_initial. #正向前迁移 > southtut:0001_initial (faked)
3、应用改变
这里添加一个字段,要把给字段给同步上去。
class Knight(models.Model): name = models.CharField(max_length=100) of_the_round_table = models.BooleanField()
dances_whenever_able = models.BooleanField() #新增
那么接下来就是同步了,此时分两个步骤:
(1)、创建迁移:manage.py schemamigration southtut --auto
E:\project\demo>manage.py schemamigration southtut --auto #此时用 --auto + Added field dances_whenever_able on southtut.Knight #做出的改变 Created 0002_auto__add_field_knight_dances_whenever_able.py. #创建迁移版本
You can now apply this migration with: ./manage.py migrate southtut
(2)、应用:manage.py migrate southtut
E:\project\demo>manage.py migrate southtut Running migrations for southtut: - Migrating forwards to 0002_auto__add_field_knight_dances_whenever_able. > southtut:0002_auto__add_field_knight_dances_whenever_able - Loading initial data for southtut. No fixtures found.
完成之后,则发现已经添加了该字段
七、深入基础教程(迁移使用)
1、基本流程
对于已经之前已经存在的model,如果我们使用south则不能使用上面的步骤。比如说,我有一个名为other的app下model早已建立并且同步至数据库,那么我想要用south,那么就要作如下处理了。
#已存在的model且里面存有数据 class Contact(models.Model): name = models.CharField(max_length=30) email = models.EmailField() comment = models.CharField(max_length=100) def __unicode__(self): return self.name class Meta: db_table='contact'
ok,我要用这个,且在model里动了手脚。
#Contact ... age = models.IntegerField() #添加
那么使用south如下:
(1)、创建迁移:(--auto)
manage.py schemamigration other --auto .....#省略
(2)、应用:
manage.py migrate other #...省略
流程给出了,但是为什么省略输出的部分呢,因为这里涉及到一个知识点,就是Defaults:
2、defaults
对于上面southtut app model存在BooleanField,则该字段默认的default=False,然而对于其他字段,可能没有定义默认字段,如果列为空,既null=True,那么新生成的列就没有威胁了,否则就必须给出默认值,因为对于已经存在数据的model,新的字段不可能没有值。一些数据库后端将让你添加列,如果表是空的,而有些会拒绝彻底。
针对这种情况,south将会给出选择并执行
#Contact ... website = models.CharField(max_length=100,null=False) #新增 ..
E:\project\demo>manage.py schemamigration other --auto ? The field 'Contact.website' does not have a default specified, yet is NOT NULL. #问题 ? Since you are adding this field, you MUST specify a default value to use for existing rows. Would you like to: ? 1. Quit now, and add a default to the field in models.py #退出,在models手动添加默认值 ? 2. Specify a one-off value to use for existing columns now #指定默认值 ? Please select a choice:
..... ? Please select a choice: 2 #我的选择 ? Please enter Python code for your one-off default value. ? The datetime module is available, so you can do e.g. datetime.date.today() >>> 'http://www.google.com' #指定的默认值 + Added field website on other.Contact #添加成功 Created 0006_auto__add_field_contact_website.py. You can now apply this migration with: ./manage.py migrate other
#应用 E:\project\demo>manage.py migrate other Running migrations for other: - Migrating forwards to 0006_auto__add_field_contact_website. > other:0006_auto__add_field_contact_website - Loading initial data for other.No fixtures found.
3、Uniques
还有一点重要的是unique属性
class Contact(models.Model): name = models.CharField(max_length=30,unique=True)#更改了 email = models.EmailField() comment = models.CharField(max_length=100) website = models.CharField(max_length=100,null=False) #新增 def __unicode__(self): return self.name class Meta: db_table='contact'
E:\project\demo>manage.py schemamigration other --auto + Added unique constraint for ['name'] on other.Contact Created 0007_auto__add_unique_contact_name.py. You can now apply this migration with: ./manage.py migrate other #还可以这样: E:\project\demo>manage.py schemamigration --auto other
然后再manage.py migrate southtut 就ok了。
4、ManyToMany fields
south能够检测多对多字段,South will create the table the ManyToMany represents, and when you remove the field, the table will be deleted.
一、迁移清单
列出某个app下的迁移清单,或整个django项目的迁移清单,相当于列出其历史记录,这时要用到
#某个app下迁移清单 manage.py migrate app_name --list #整个项目迁移清单 manage.py migrate --list
显示如下。注意带*的为已经应用到了 ,()表示尚未应用到的。
E:\project\demo>manage.py migrate other --list other (*) 0001_initial (*) 0002_auto__add_action__del_field_contact_age__add_field_contact_comment (*) 0003_initial (*) 0004_initial (*) 0005_initial (*) 0006_auto__add_field_contact_website (*) 0007_auto__add_unique_contact_name (*) 0008_auto__add_field_action_keys (*) 0009_auto__del_field_action_keys (*) 0010_auto__del_action
二、数据迁移
第一节所涉及的是模式迁移,涉及表、字段、索引的添加和删除;另一种迁移就是数据迁移。
数据迁移是用来改变你的数据库中存储的数据匹配一个新的模式,或特性。
例如,如果你一直以纯文本形式保存密码,现在你需要以利用salt对密码进行散列 的形式,这样就涉及到数据的迁移以适应新的模式。可能有以下三个步骤(每个步骤对应一个迁移):
(1)、创建两列:password_salt 和password_hash (a schema migration).
(2)、使用旧密码的列的内容,计算每个用户的密码后应用到新的列(a data migration)
(3)、移除旧的密码列(a schema migration).
class User(models.Model): username = models.CharField(max_length=255) password = models.CharField(max_length=60)
假设有用户:Jack,密码:admin123.如果以文本的形式肯定不安全了,那么现在就利用salt对密码进行散列。
import sha class User(models.Model): username = models.CharField(max_length=255) password = models.CharField(max_length=60)
password_salt = models.CharField(max_length=8, null=True)
password_hash = models.CharField(max_length=40, null=True) def check_password(self, password): return sha.sha(self.password_salt+password).hexdigest() == self.password_hash """ 用户注册的过程:
1)用户提供密码(以及其他用户信息);
2)系统为用户生成Salt值;
3)系统将Salt值和用户密码连接到一起;
4)对连接后的值进行散列,得到Hash值;
5)将Hash值和Salt值分别放到数据库中。
用户登录的过程:
1)用户提供用户名和密码;
2)系统通过用户名找到与之对应的Hash值和Salt值;
3)系统将Salt值和用户提供的密码连接到一起;
4)对连接后的值进行散列,得到Hash'(注意有个“撇”);
5)比较Hash和Hash'是否相等,相等则表示密码正确,否则表示密码错误。 """
接下来就是创建模式迁移将会创建两列:
E:\project\demo>manage.py schemamigration other --auto + Added field password_salt on other.User + Added field password_hash on other.User Created 0013_auto__add_field_user_password_salt__add_field_user_password_hash.py . You can now apply this migration with: ./manage.py migrate other
那么接下来就是创建数据迁移了,
E:\project\demo>manage.py datamigration other hash_passwords Created 0014_hash_passwords.py.
打开 0014_hash_passwords.py 文件 发现如下,我们还需要手写forwards、backwards方法
更改如下:
# -*- coding: utf-8 -*- import datetime from south.db import db from south.v2 import DataMigration from django.db import models class Migration(DataMigration): def forwards(self, orm): import random,sha,string for user in orm.User.objects.all(): #更新数据 user.password_salt = "".join([random.choice(string.letters) for i in range(8)]) user.password_hash = sha.sha(user.password_salt + user.password).hexdigest() user.save() def backwards(self, orm): raise RuntimeError("Cannot reverse this migration.") ......
注意这里的orm.User,对象关系映射(Object Relational Mapping) 这里关系到其迁移的model,如User model。如果用数据迁移中使用其他app的model则用orm['contenttypes.ContentType']. Models
If you want to access models from other apps in your data migration, use a syntax likeorm['contenttypes.ContentType']. Models will be available if you can somehow get to them via ForeignKey or ManyToMany traversal from your app’s models; if you want to freeze other models, simply pass--freeze appname on the datamigration command line.
最后在backwards()方法中引发错误,因为这个过程本质上是不可逆转的。就是说只能向前迁移,不能向后。
最后步骤:删除password字段,启动迁移
E:\project\demo>manage.py schemamigration other --auto ? The field 'User.password' does not have a default specified, yet is NOT NULL. ? Since you are removing this field, you MUST specify a default ? value to use for existing rows. Would you like to: ? 1. Quit now. ? 2. Specify a one-off value to use for existing columns now ? 3. Disable the backwards migration by raising an exception; you can edit the migration to fix it later ? Please select a choice: 2 ? Please enter Python code for your one-off default value. ? The datetime module is available, so you can do e.g. datetime.date.today() >>> "" - Deleted field password on other.User Created 0015_auto__del_field_user_password.py. You can now apply this migration with: ./manage.py migrate other
接下来就是应用这3个迁移:
E:\project\demo>manage.py migrate other Running migrations for other: - Migrating forwards to 0004_auto__del_field_user_password. > southtut2:0002_auto__add_field_user_password_salt__add_field_user_password_hash > southtut2:0003_hash_passwords > southtut2:0004_auto__del_field_user_password - Loading initial data for other.
接下来验证一下:
>>> from other.models import User >>> User.objects.get(id=1).check_password('admin123') True >>> User.objects.get(id=1).check_password('admin3') False
<script>window._bd_share_config={"common":{"bdSnsKey":{},"bdText":"","bdMini":"2","bdMiniList":false,"bdPic":"","bdStyle":"0","bdSize":"16"},"share":{}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)];</script>
阅读(7443) | 评论(0) | 转发(0) |
0
上一篇:python中几个内置函数的用法
下一篇:python图像处理库PIL介绍
相关热门文章
ASP使用内置对象前不必创建...
bootStrap中Tab页签切换
京东SSO单点登陆实现分析...
WebRTC学习笔记
强大的http调试工具charles用...
linux dhcp peizhi roc
关于Unix文件的软链接
求教这个命令什么意思,我是新...
sed -e "/grep/d" 是什么意思...
谁能够帮我解决LINUX 2.6 10...
给主人留下些什么吧!~~
评论热议
相关文章推荐
- 强大的jquery上传插件SWF版Uploadify参数详解
- openstack页面自定义插件使用详解(django、ajax、post)(zTree为例)
- 详解python如何在django中为用户模型添加自定义权限
- Django模型层Meta内部类详解
- Django模型层Meta内部详解
- Django:模型管理工具South
- Django开发之south详解
- Django模型设计详解系列之三
- Django(5)模型models定义详解
- python django模型内部类meta详解
- Django模型层Meta内部类详解
- Three.js如何用轨迹球插件(trackball)增加对模型的交互功能详解
- django 模型 models详解
- Django模型层Meta内部类详解
- django-evolution 插件维持Django 模型和数据库结构一致的基本原理
- Three.js利用orbit controls插件(轨道控制)控制模型交互动作详解
- 全网最详细的如何在谷歌浏览器里正确下载并安装Postman【一款功能强大的网页调试与发送网页HTTP请求的Chrome插件】(图文详解)
- Django学习之模型的操作详解
- Django模型字段选项详解
- Django中South插件的使用