Django CreateView保存后self.object.pk返回None问题修复
问题根源
你拿不到新保存记录主键的核心原因是模型主键字段配置错误:
- 你将主键
id定义为普通的models.IntegerField(primary_key=True),没有使用Django约定的自增主键类型AutoField/BigAutoField。这种情况下Django ORM默认主键值需要开发者手动赋值,执行INSERT保存数据后,不会主动拉取数据库侧自增生成的主键值回填到模型实例上,自然self.object.pk、form.instance.pk都会返回None。 - 模型Meta类配置了
managed = False,Django不负责该表的结构维护,也不会自动适配数据库层面已有的自增主键逻辑,进一步加剧了这个问题。
补充:你URL配置里的name拼写前后不一致,定义时写的是asignacion_contact,问题描述里写的是assignacion_contact,后续反向解析的时候注意别写错。
解决方法
二选一即可:
一劳永逸改模型字段(推荐)
把模型里的主键字段改成自增类型即可,AutoField本质就是适配数据库自增逻辑的整数字段,和你现有数据库里的int类型自增主键完全兼容,加上你已经设置了managed=False,这次修改不会触发任何表结构变更,没有副作用:# model.py 里修改AsignacionContact类的id字段 class AsignacionContact(models.Model): # 把原来的IntegerField改成AutoField,如果数据库里id是bigint类型就换成BigAutoField id = models.AutoField(primary_key=True) # 其余字段、Meta类、__str__方法全部保持原有代码不变 idasignacion_general = models.ForeignKey('AsignacionGeneral', models.DO_NOTHING, db_column='idasignacion_general') nombre_asignacion = models.CharField(max_length=100) fecha_inicio = models.DateField() fecha_fin = models.DateField() observacion = models.CharField(max_length=255, blank=True, null=True) estado = models.IntegerField(blank=True, null=True)改完之后你原有
form_valid、get_success_url里的代码不需要任何调整,保存后就能正常拿到self.object.pk的值。不改模型,手动取最后插入ID
如果你不想调整模型字段定义,可以在调用完父类的form_valid方法后,直接通过数据库连接取最后插入的ID赋值给实例,再做后续操作:# view.py 顶部先引入connection from django.db import connection # 再修改form_valid方法 def form_valid(self, form): isvalid = super().form_valid(form) # 直接从数据库游标取最后插入的主键ID last_inserted_id = connection.cursor().lastrowid self.object.pk = last_inserted_id form.instance.pk = last_inserted_id print('form_valid') print(form.instance.pk) print(self.object.pk) return isvalid注意:不要直接用
self.object.refresh_from_db(),这个方法本身需要实例持有主键值才能查库,在pk为None的时候调用会直接报错。
内容的提问来源于stack exchange,提问作者cudris
相关产品推荐
相关产品推荐

