RunPython.noop()有什么作用?
在文档中它说,
“当您希望操作不在给定方向上做任何事情时,将 RunPython.noop 方法传递给 code 或 reverse_code。这在使操作可逆时特别有用。”
回答
有时您可能想要还原迁移。例如,您添加了一个字段,但现在您想将数据库恢复到迁移前的状态。您可以通过使用以下命令恢复迁移[Django-doc]来做到这一点:
python3 manage.py migrate app_name previous_migration_name
然后 Django 将查看它如何迁移回previous_migration_name
并执行必要的操作。例如,如果您将字段从foo
tobar
重命名,那么 Django 会将其从bar
back重命名为foo
.
其他操作不可逆。例如,如果您在迁移中删除了一个字段,而该字段没有默认值且NULL
无法使用,则无法撤消。这是有道理的,因为删除字段的反面是添加一个字段,但是由于现有记录没有值,Django 应该为为现有记录重新创建的那个字段填写什么?
一个RunPython
命令在默认情况下不可逆的。一般而言,在计算机科学中,如果存在函数,则无法通过计算确定函数的反转。这是莱斯定理[wiki] 的结果。但有时是可能的。例如,如果我们构建了一个迁移,其中我们将某个字段加一,那么反过来就是将所有字段减一,例如:
from django.db.models import F
from django.db import migrations
def forwards_func(apps, schema_editor):
MyModel = apps.get_model('my_app', 'MyModel')
db_alias = schema_editor.connection.alias
MyModel.objects.using(db_alias).all().update(
some_field=F('some_field')+1
])
def reverse_func(apps, schema_editor):
MyModel = apps.get_model('my_app', 'MyModel')
db_alias = schema_editor.connection.alias
MyModel.objects.using(db_alias).all().update(
some_field=F('some_field')-1
])
class Migration(migrations.Migration):
dependencies = []
operations = [
migrations.RunPython(code=forwards_func, reverse_code=reverse_func),
]
但有时(数据)迁移可能在您向前迁移时什么也不做,或者在向后迁移时更常见。您可以将引用传递给noop
,而不是每次都实现一个空函数,它什么都不做:
from django.db.models import F
from django.db import migrations
def forwards_func(apps, schema_editor):
# … some action …
pass
class Migration(migrations.Migration):
dependencies = []
operations = [
migrations.RunPython(code=forwards_func, reverse_code=migrations.RunPython.noop),
]