Model层之Migration
1、Migration介绍
Migration 是Django用来将你对models做的改变 (添加一个字段,删除一个model等等) 同步到数据库模式中。
主要用到下面的几个命令:
- migrate, 主要负责同步;
- makemigrations, 基于对models做的变化创建新的migration。
2、工作流程
1)当对数据模型做出改变之后,执行python manage.py makemigrations x_app,这是收集某个APP下面的变动。
Migrations for 'books':
0003_auto.py:
- Alter field author on book
执行命令后,模型将被浏览,然后和已经存在的migrations 文件进行比较,然后生成新的migration文件集合。实际上就是讲SQL语句收集起来,但并没有同步到数据库。
migratons文件其实就是普通的py文件。下面是一个初始化文件0001_initial.py(创建数据库):
class Migration(migrations.Migration):
initial = True
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='Article',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(max_length=150, unique=True, verbose_name='\u6807\u9898')),
('alias', models.CharField(max_length=150, verbose_name='\u82f1\u6587\u6807\u9898')),
('content', models.TextField(verbose_name='\u6b63\u6587')),
('content_html', models.TextField(verbose_name='\u6b63\u6587html\u683c\u5f0f')),
('abstract', models.TextField(verbose_name='\u6458\u8981')),
('read_times', models.IntegerField(default=0, verbose_name='\u9605\u8bfb\u6b21\u6570')),
('tags', models.CharField(help_text='\u7528\u9017\u53f7\u9694\u5f00', max_length=100, verbose_name='\u6807\u7b7e')),
('status', models.IntegerField(choices=[(0, '\u6b63\u5e38'), (1, '\u8349\u7a3f'), (2, '\u5220\u9664')], default=0, verbose_name='\u6587\u7ae0\u72b6\u6001')),
('create_time', models.DateTimeField(auto_now_add=True)),
('pub_time', models.DateTimeField(default=datetime.datetime(2016, 4, 25, 13, 30, 50, 995000))),
('update_time', models.DateTimeField(auto_now=True)),
('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='\u4f5c\u8005')),
],
options={
'ordering': ['-pub_time', '-create_time'],
'get_latest_by': 'create_time',
'verbose_name': '\u6587\u7ae0',
},
),
migrations.CreateModel(
name='Category',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=150, unique=True, verbose_name='\u7c7b\u540d')),
('alias', models.CharField(max_length=150, verbose_name='\u82f1\u6587\u540d\u79f0')),
('status', models.IntegerField(choices=[(0, '\u6b63\u5e38'), (1, '\u8349\u7a3f'), (2, '\u5220\u9664')], default=0, verbose_name='\u72b6\u6001')),
('create_time', models.DateTimeField(auto_now_add=True)),
('parent', models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.CASCADE, to='blog.Category', verbose_name='\u4e0a\u7ea7\u5206\u7c7b')),
],
options={
'ordering': ['-create_time'],
'verbose_name': '\u5206\u7c7b',
},
),
migrations.AddField(
model_name='article',
name='category',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='blog.Category', verbose_name='\u5206\u7c7b'),
),
]
Migration主要有initial,dependency和operation等常用选项。
operation有CreateModel,DeleteModel,ADDField,AlterField等等。
Django源码在django.db.migrations中。
2)执行命令python manage.py migrate
Operations to perform:
Apply all migrations: books
Running migrations:
Rendering model states... DONE
Applying books.0003_auto... OK
该文件扫描变动后的migrations文件,并操作数据库。 注意:上个命令是全局检测的,经常出现No changes detected,所以最好还是加条件选项,指定app。
3、列出所有的迁移情况
Python manager.py makemigrations --list
该命令会列出所有的模型初始化以及变更情况。
4、初始化auth相关模型
当我们第一次执行migrate的时候也会生成user,goup相关模型。它的原理如下: 首先在setting.py定义INSTALLED_APPS:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'blog',
'rest_framework'
]
'django.contrib.auth'为Django项目中的一个app,然后看Django的源码。在django.contrib.auth中,也有一个migrations文件。果不其然也有一个0001_initial.py文件:
class Migration(migrations.Migration):
dependencies = [
('contenttypes', '__first__'),
]
operations = [
migrations.CreateModel(
name='Permission',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('name', models.CharField(max_length=50, verbose_name='name')),
('content_type', models.ForeignKey(
to='contenttypes.ContentType',
on_delete=models.CASCADE,
to_field='id',
verbose_name='content type',
)),
('codename', models.CharField(max_length=100, verbose_name='codename')),
],
options={
'ordering': ('content_type__app_label', 'content_type__model', 'codename'),
'unique_together': set([('content_type', 'codename')]),
'verbose_name': 'permission',
'verbose_name_plural': 'permissions',
},
managers=[
('objects', django.contrib.auth.models.PermissionManager()),
],
),
migrations.CreateModel(
name='Group',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('name', models.CharField(unique=True, max_length=80, verbose_name='name')),
('permissions', models.ManyToManyField(to='auth.Permission', verbose_name='permissions', blank=True)),
],
options={
'verbose_name': 'group',
'verbose_name_plural': 'groups',
},
managers=[
('objects', django.contrib.auth.models.GroupManager()),
],
),
migrations.CreateModel(
name='User',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('password', models.CharField(max_length=128, verbose_name='password')),
('last_login', models.DateTimeField(default=timezone.now, verbose_name='last login')),
('is_superuser', models.BooleanField(
default=False,
help_text='Designates that this user has all permissions without explicitly assigning them.',
verbose_name='superuser status'
)),
('username', models.CharField(
help_text='Required. 30 characters or fewer. Letters, digits and @/./+/-/_ only.', unique=True,
max_length=30, verbose_name='username',
validators=[validators.RegexValidator('^[\\w.@+-]+$', 'Enter a valid username.', 'invalid')]
)),
('first_name', models.CharField(max_length=30, verbose_name='first name', blank=True)),
('last_name', models.CharField(max_length=30, verbose_name='last name', blank=True)),
('email', models.EmailField(max_length=75, verbose_name='email address', blank=True)),
('is_staff', models.BooleanField(
default=False, help_text='Designates whether the user can log into this admin site.',
verbose_name='staff status'
)),
('is_active', models.BooleanField(
default=True, verbose_name='active', help_text=(
'Designates whether this user should be treated as active. Unselect this instead of deleting '
'accounts.'
)
)),
('date_joined', models.DateTimeField(default=timezone.now, verbose_name='date joined')),
('groups', models.ManyToManyField(
to='auth.Group', verbose_name='groups', blank=True, related_name='user_set',
related_query_name='user', help_text=(
'The groups this user belongs to. A user will get all permissions granted to each of their '
'groups.'
)
)),
('user_permissions', models.ManyToManyField(
to='auth.Permission', verbose_name='user permissions', blank=True,
help_text='Specific permissions for this user.', related_name='user_set',
related_query_name='user')
),
],
options={
'swappable': 'AUTH_USER_MODEL',
'verbose_name': 'user',
'verbose_name_plural': 'users',
},
managers=[
('objects', django.contrib.auth.models.UserManager()),
],
),
]
看上面的代码已经很清楚了,定义了goup,user,permission等Model。
微信分享/微信扫码阅读