无法插入数据,Django 主键没有默认

时间:2021-03-16 13:19:28

标签: django

在 Django 3.0 中,我有一组模型,其中包含一个抽象 BaseData、一个扩展它的模型 Data 和一个 FKData 的底层数据模型 {{1}外键:

Data

当我尝试插入 # models.py from django.db import models class BaseData(models.Model): class Meta: abstract = True class Data(BaseData): data = models.ForeignKey( FKData, on_delete=models.CASCADE, blank=True, null=True, default=None ) class FKData(models.Model): text = models.CharField( help_text='underlying data' ) 时发生错误。例如,

Data

mysql> INSERT INTO appname_data (data_id) SELECT data_id FROM appname_othertable ERROR 1364 (HY000): Field 'basedata_ptr_id' doesn't have a default value 是 Django 生成的主键字段,basedata_ptr_id 由于是 Data 的子类而具有:

BaseData

错误听起来好像没有像普通主键那样设置为 mysql> DESCRIBE appname_data; +-----------------+---------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-----------------+---------+------+-----+---------+-------+ | basedata_ptr_id | int(11) | NO | PRI | NULL | | | data_id | int(11) | YES | MUL | NULL | | +-----------------+---------+------+-----+---------+-------+ 2 rows in set (0.00 sec)

如果我尝试使用 Django shell 填充 AUTO INCREMENT 表,我会得到同样的错误,但有一个可能有用的更大的堆栈跟踪:

Data

出了什么问题,我该如何解决?

编辑:我决定擦除我的数据库并停止所有开发,同时我花了几个星期重建它,这都是因为我忽略了一行,因为我正在使用“具有截止日期的完美主义者的框架。”

尽管如此,这个问题值得更好的回答。根据评论,我怀疑接近答案的最佳方法如下:

考虑两种情况。

场景 A

  1. 我将 Traceback (most recent call last): File "/home/username/ProjectName/env/lib/python3.6/site-packages/django/db/backends/utils.py", line 86, in _execute return self.cursor.execute(sql, params) File "/home/username/ProjectName/env/lib/python3.6/site-packages/django/db/backends/mysql/base.py", line 74, in execute return self.cursor.execute(query, args) File "/home/username/ProjectName/env/lib/python3.6/site-packages/MySQLdb/cursors.py", line 209, in execute res = self._query(query) File "/home/username/ProjectName/env/lib/python3.6/site-packages/MySQLdb/cursors.py", line 315, in _query db.query(q) File "/home/username/ProjectName/env/lib/python3.6/site-packages/MySQLdb/connections.py", line 239, in query _mysql.connection.query(self, query) MySQLdb._exceptions.IntegrityError: (1364, "Field 'basedata_ptr_id' doesn't have a default value") The above exception was the direct cause of the following exception: Traceback (most recent call last): File "<console>", line 6, in <module> File "/home/username/ProjectName/env/lib/python3.6/site-packages/django/db/models/base.py", line 746, in save force_update=force_update, update_fields=update_fields) File "/home/username/ProjectName/env/lib/python3.6/site-packages/django/db/models/base.py", line 784, in save_base force_update, using, update_fields, File "/home/username/ProjectName/env/lib/python3.6/site-packages/django/db/models/base.py", line 887, in _save_table results = self._do_insert(cls._base_manager, using, fields, returning_fields, raw) File "/home/username/ProjectName/env/lib/python3.6/site-packages/django/db/models/base.py", line 926, in _do_insert using=using, raw=raw, File "/home/username/ProjectName/env/lib/python3.6/site-packages/django/db/models/manager.py", line 82, in manager_method return getattr(self.get_queryset(), name)(*args, **kwargs) File "/home/username/ProjectName/env/lib/python3.6/site-packages/django/db/models/query.py", line 1204, in _insert return query.get_compiler(using=using).execute_sql(returning_fields) File "/home/username/ProjectName/env/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 1391, in execute_sql cursor.execute(sql, params) File "/home/username/ProjectName/env/lib/python3.6/site-packages/django/db/backends/utils.py", line 100, in execute return super().execute(sql, params) File "/home/username/ProjectName/env/lib/python3.6/site-packages/django/db/backends/utils.py", line 68, in execute return self._execute_with_wrappers(sql, params, many=False, executor=self._execute) File "/home/username/ProjectName/env/lib/python3.6/site-packages/django/db/backends/utils.py", line 77, in _execute_with_wrappers return executor(sql, params, many, context) File "/home/username/ProjectName/env/lib/python3.6/site-packages/django/db/backends/utils.py", line 86, in _execute return self.cursor.execute(sql, params) File "/home/username/ProjectName/env/lib/python3.6/site-packages/django/db/utils.py", line 90, in __exit__ raise dj_exc_value.with_traceback(traceback) from exc_value File "/home/username/ProjectName/env/lib/python3.6/site-packages/django/db/backends/utils.py", line 86, in _execute return self.cursor.execute(sql, params) File "/home/username/ProjectName/env/lib/python3.6/site-packages/django/db/backends/mysql/base.py", line 74, in execute return self.cursor.execute(query, args) File "/home/username/ProjectName/env/lib/python3.6/site-packages/MySQLdb/cursors.py", line 209, in execute res = self._query(query) File "/home/username/ProjectName/env/lib/python3.6/site-packages/MySQLdb/cursors.py", line 315, in _query db.query(q) File "/home/username/ProjectName/env/lib/python3.6/site-packages/MySQLdb/connections.py", line 239, in query _mysql.connection.query(self, query) django.db.utils.IntegrityError: (1364, "Field 'basedata_ptr_id' doesn't have a default value") 定义为抽象类
BaseData
  1. 我运行 class BaseData(models.Model): class Meta: abstract = True 来创建迁移文件

场景 B

  1. 我将 makemigrations 定义为非抽象类
BaseData
  1. 我运行 class BaseData(models.Model): class Meta: pass 来创建迁移文件。
  2. 我将 makemigrations 更改为抽象类
BaseData
  1. 我运行 class BaseData(models.Model): class Meta: abstract = True 来创建第二个迁移文件。

原则上,从场景 B 的两次迁移的组合应该与从场景 A 的迁移完全相等。在实践中,有些事情是不同的。回答这个问题的第一步是确定这两种方案之间的迁移指令有何不同。然后,我们可以制定一个手动编辑迁移文件的流程来解决问题,而无需擦除数据库,以供日后遇到同样问题的人使用。

0 个答案:

没有答案
相关问题