在模型级别解决这个问题很重要,而不是在表单级别,因为数据可以通过 API、导入脚本、shell 等输入。null=True
在 CharField 上设置的缺点是该列可能最终都为空字符串和 NULL,这有点模棱两可,但根据我的经验,这通常不是问题。如果您愿意忍受这种模棱两可的情况,请按照以下步骤操作:
1)null=True, blank=True
在现场设置并在更改中迁移。
2)按摩您的数据,以便将所有现有的空字符串更改为 NULL:
items = Foo.objects.all()
for item in items:
if not item.somefield:
item.somefield = None
item.save()
3)save()
向您的模型添加自定义方法:
def save(self, *args, **kwargs):
# Empty strings are not unique, but we can save multiple NULLs
if not self.somefield:
self.somefield = None
super().save(*args, **kwargs) # Python3-style super()
4)unique=True
在现场设置并迁移。
现在,somefield
无论您使用管理员还是任何其他数据输入方法,您都可以将其存储为空值或唯一值。
如果您不想进行多次迁移,以下是如何在一次迁移中进行的示例:
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
def set_nulls(apps, schema_editor):
Event = apps.get_model("events", "Event")
events = Event.objects.all()
for e in events:
if not e.wdid:
e.wdid = None
e.save()
class Migration(migrations.Migration):
dependencies = [
('events', '0008_something'),
]
operations = [
migrations.AlterField(
model_name='event',
name='wdid',
field=models.CharField(blank=True, max_length=32, null=True),
),
migrations.RunPython(set_nulls),
migrations.AlterField(
model_name='event',
name='wdid',
field=models.CharField(blank=True, max_length=32, null=True, unique=True),
),
]