You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为使用UUIDField作为主键的Django模型添加非主键AutoField或serial字段

解决Django UUID主键下添加自增字段的问题

我之前也碰到过一模一样的场景——用UUID做主键,但业务上需要一个连续自增的编号,下面是亲测有效的解决方案:

1. 正确定义模型

先保留UUID作为主键,同时添加自增字段,关键要设置blank=True(允许Admin表单留空)和null=False(数据库字段不允许为空):

import uuid
from django.db import models

class YourModel(models.Model):
    id = models.UUIDField(
        primary_key=True,
        default=uuid.uuid4,
        editable=False
    )
    # 业务自增编号
    number = models.IntegerField(
        unique=True,
        blank=True,
        null=False
    )

    def __str__(self):
        return f"{self.number} - {self.id}"

2. 生成并修改迁移文件

先执行python manage.py makemigrations生成初始迁移,然后打开生成的迁移文件,添加创建序列和设置字段默认值的SQL操作:

from django.db import migrations, models
import uuid

class Migration(migrations.Migration):
    dependencies = [
        # 这里填写你的依赖迁移,比如('yourapp', '0001_initial')
    ]

    operations = [
        migrations.CreateModel(
            name='YourModel',
            fields=[
                ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
                ('number', models.IntegerField(null=False, unique=True)),
            ],
        ),
        # 创建序列,起始值设为100000
        migrations.RunSQL(
            sql="CREATE SEQUENCE yourmodel_number_seq START 100000;",
            reverse_sql="DROP SEQUENCE IF EXISTS yourmodel_number_seq;"
        ),
        # 给number字段设置默认值为序列的下一个值
        migrations.RunSQL(
            sql="ALTER TABLE yourmodel ALTER COLUMN number SET DEFAULT nextval('yourmodel_number_seq');",
            reverse_sql="ALTER TABLE yourmodel ALTER COLUMN number DROP DEFAULT;"
        ),
    ]

3. 执行迁移

运行python manage.py migrate完成数据库变更。

4. 验证效果

现在通过Admin后台添加对象时,不需要手动输入number字段,数据库会自动从100000开始生成自增编号,完全不会和UUID主键冲突。

为什么之前的db_type='serial'没生效?

PostgreSQL的serial类型本质是IntegerField + 自动创建序列 + 默认值为nextval,但直接在Django字段里设置db_type='serial'时,Django不会自动处理Admin表单的空白提交逻辑:如果没设置blank=True,Admin会强制要求输入该字段,否则会传入null覆盖数据库的默认值,导致存储为null。上面的方案手动控制了序列和默认值,同时通过blank=True让Admin允许留空,完美解决了这个问题。

内容的提问来源于stack exchange,提问作者Basel J. Hamadeh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 03:33:40