[英]Adding a Non-Primary Key AutoField or a 'serial' field in a Django Model which uses a UUID field as a Primary Field
我正在构建一个以 UUIDField 作为主键的模型。 但我的用例需要。 也有一个自动增量字段。 Django 提供了一个 AutoField。 但是需要有 primary_key=True ,在我的情况下我不想要,因为我使用 UUIDField 作为primary_key。
我尝试创建一个字段并赋予 db_type 'serial' 并添加一个迁移,该迁移改变了在 100000 处重新启动的序列.. 使用 Admin 将对象添加到数据库将始终将数字字段存储为空值。 如果我删除 null=True。 然后保存将失败,因为它需要数字字段的值。
如何在保持 UUIDField 作为主键的同时使数字字段递增?
fields.py
class SerialField(models.Field):
description = _("BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE")
empty_strings_allowed = False
default_error_messages = {
'invalid': _("'%(value)s' value must be an integer."),
}
def __init__(self, *args, **kwargs):
kwargs['blank'] = True
super().__init__(*args, **kwargs)
def db_type(self, connection):
return 'serial'
models.py
from .fields import SerialField
class MyModel(models.Model):
uuid = models.UUIDField(
verbose_name=_("UUID Identifier"),
primary_key=True,
default=uuid.uuid4,
editable=False,
help_text=_("Requried, PrimaryKey none-editable"),
db_index=True,
)
number = SerialField(
primary_key=False,
editable=False,
help_text=_("Auto Increment Number"),
verbose_name=_("Number"),
#null=True
)
0002_auto_20180202.py
从 django.db 导入迁移
def forwards(apps, schema_editor):
if schema_editor.connection.alias == 'default':
return migrations.RunSQL(
"ALTER SEQUENCE app_name_mymodel_number_seq RESTART WITH 100000"
)
class Migration(migrations.Migration):
dependencies = [
('activities', '0001_initial'),
]
operations = [
migrations.RunPython(forwards)
]
也试过这个。 我的解决方法是改用原始 SQL。
迁移:
migrations.RunSQL(
"CREATE SEQUENCE sequence_name START 100000",
reverse_sql="DROP SEQUENCE IF EXISTS sequence_name",
elidable=False,
),
型号:
def get_next_increment():
with connection.cursor() as cursor:
cursor.execute("SELECT nextval('sequence_name')")
result = cursor.fetchone()
return result[0]
class MyModel(models.Model):
my_field = models.IntegerField(default=get_next_increment, editable=False, unique=True)
为了举例,让我们假设我们的表的名称是payouts
以下将是支付模型:
class Payouts(models.Model):
# seq_id = models.IntegerField()
# we will create seq_id auto-increment by raw SQL
id = models.UUIDField(primary_key=True)
class Meta:
managed = True
db_table = 'payouts'
您可以看到我们希望将id与 uuid 作为主键。
请按照以下说明操作:
步骤 1:为上述模型制作迁移文件。
python manage.py makemigrations
第 2 步:生成空迁移以执行 SQL 查询:
python manage.py makemigrations --empty -n dont_delete_add_defaults_sql
第 3 步:编辑dont_delete_add_defaults_sql如下:
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('apiapp', '0001_initial'), #Replace 0001_initial with the name of file generated in step 1
]
operations = [
migrations.RunSQL("ALTER TABLE payouts ADD seq_id serial NOT NULL;"),
migrations.RunSQL("DROP SEQUENCE IF EXISTS payouts_seq_id_seq CASCADE;"),
migrations.RunSQL("create sequence payouts_seq_id_seq owned by payouts.seq_id;"),
migrations.RunSQL("alter table payouts alter column seq_id set default nextval('payouts_seq_id_seq');"),
]
第 4 步:运行最终迁移
python manage.py migrate
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.