架构迁移和默认值

Posted

技术标签:

【中文标题】架构迁移和默认值【英文标题】:Schema Migrations and Default Values 【发布时间】:2013-04-17 20:43:04 【问题描述】:

我正在使用 South 来管理我的数据库。似乎每次我在创建模型的方式上进行一些细微的更改时,我最终都不得不为迁移做一堆体操。例如,假设我有一个这样的类:

class Entry(models.Model):

    title = models.CharField(max_length=80)
    author = models.ForeignKey(User)
    pubDate = models.DateTimeField()
    tags = models.ManyToManyField(Tag)
    text = models.TextField()

还有另一个以 Entry 作为外键的类:

class Comment(models.Model):
    author = models.ForeignKey(User)
    entry = models.ForeignKey(Entry)
    pubDate = models.DateTimeField()
    text = models.TextField()

这很简单,但如果我要做一些简单的事情,例如将名称 pubDate 更改为 Entry 中的 pub_date,为了仅针对此名称更改正确执行架构迁移,我必须设置:

default=None, null=True

对于Entry 中的 pubDate 和 Comment 中的 entry 字段,否则在尝试运行迁移时会出现以下异常:

The field 'Comment.entry' does not have a default specified, yet is NOT NULL.

那么我将不得不返回并取出默认/空值。有没有一种不那么乏味的方法来做到这一点,还是我只需要在将模型提交到迁移之前真正考虑一下我的模型?在开始阶段,如果您没有任何您关心保留的数据,那么仅设置和拆除数据库是否更有意义?如果是这样,最简单的方法是什么?

【问题讨论】:

【参考方案1】:

你需要创建一个迁移类,使用:

python manage.py datamigration yourapp change_name_to_pub_date

并重写forwards和backwards方法:

# -*- coding: utf-8 -*-
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models


class Migration(SchemaMigration):
    def forwards(self, orm):
        db.rename_column('yourapp_entry', 'pubDate', 'pub_date')
        db.rename_column('yourapp_comment', 'pubDate', 'pub_date')

    def backwards(self, orm):
        db.rename_column('yourapp_entry', 'pub_date', 'pubDate')
        db.rename_column('yourapp_comment', 'pub_date', 'pubDate')

现在,运行:

python manage.py migrate yourapp

【讨论】:

以上是关于架构迁移和默认值的主要内容,如果未能解决你的问题,请参考以下文章

雄辩的 ORM 和 postgres 迁移 - 是不是可以分配表达式默认值?

Laravel 迁移:添加具有现有列默认值的列

Laravel 迁移默认值

创建迁移文件时分配默认值

Laravel:迁移更改列的默认值(布尔值)

Eloquent:带有时间戳的无效默认值