我有两个类,其中一个是另一个类的后代,我想让它们成为同一基类的同类兄弟类.
之前:
from django.db import models
class A(models.Model):
name = models.CharField(max_length=10)
class B(models.Model):
title = models.CharField(max_length=10)
Run Code Online (Sandbox Code Playgroud)
后:
from django.db import models
class Base(models.Model):
name = models.CharField(max_length=10)
class A(Base):
pass
class B(Base):
title = models.CharField(max_length=10)
Run Code Online (Sandbox Code Playgroud)
当我生成模式迁移时,这是输出,包括我对问题的回答:
+ Added model basetest.Base
? The field 'B.a_ptr' does not have a default specified, yet is NOT NULL.
? Since you are removing this field, you MUST specify a default
? value to use for existing rows. Would you like to:
? 1. Quit now, and add a default to the field in models.py
? 2. Specify a one-off value to use for existing columns now
? 3. Disable the backwards migration by raising an exception.
? Please select a choice: 3
- Deleted field a_ptr on basetest.B
? The field 'B.base_ptr' does not have a default specified, yet is NOT NULL.
? Since you are adding this field, you MUST specify a default
? value to use for existing rows. Would you like to:
? 1. Quit now, and add a default to the field in models.py
? 2. Specify a one-off value to use for existing columns now
? Please select a choice: 2
? Please enter Python code for your one-off default value.
? The datetime module is available, so you can do e.g. datetime.date.today()
>>> 37
+ Added field base_ptr on basetest.B
? The field 'A.id' does not have a default specified, yet is NOT NULL.
? Since you are removing this field, you MUST specify a default
? value to use for existing rows. Would you like to:
? 1. Quit now, and add a default to the field in models.py
? 2. Specify a one-off value to use for existing columns now
? 3. Disable the backwards migration by raising an exception.
? Please select a choice: 3
- Deleted field id on basetest.A
? The field 'A.name' does not have a default specified, yet is NOT NULL.
? Since you are removing this field, you MUST specify a default
? value to use for existing rows. Would you like to:
? 1. Quit now, and add a default to the field in models.py
? 2. Specify a one-off value to use for existing columns now
? 3. Disable the backwards migration by raising an exception.
? Please select a choice: 3
- Deleted field name on basetest.A
? The field 'A.base_ptr' does not have a default specified, yet is NOT NULL.
? Since you are adding this field, you MUST specify a default
? value to use for existing rows. Would you like to:
? 1. Quit now, and add a default to the field in models.py
? 2. Specify a one-off value to use for existing columns now
? Please select a choice: 2
? Please enter Python code for your one-off default value.
? The datetime module is available, so you can do e.g. datetime.date.today()
>>> 73
+ Added field base_ptr on basetest.A
Created 0002_auto__add_base__del_field_b_a_ptr__add_field_b_base_ptr__del_field_a_i.py. You can now apply this migration with: ./manage.py migrate basetest
Run Code Online (Sandbox Code Playgroud)
我不知道如何回答有关B.base_ptr和A.base_ptr的默认值的问题.我给出的任何常量都会导致迁移在运行时失败,并输出:
FATAL ERROR - The following SQL query failed: CREATE TABLE "_south_new_basetest_a" ()
The error was: near ")": syntax error
RuntimeError: Cannot reverse this migration. 'B.a_ptr' and its values cannot be restored.
Run Code Online (Sandbox Code Playgroud)
顺便说一下,当我使用sqlite3时,这就是结果.使用Postgres给出这样的东西:
FATAL ERROR - The following SQL query failed: ALTER TABLE "basetest_a" ADD COLUMN "base_ptr_id" integer NOT NULL PRIMARY KEY DEFAULT 73;
The error was: could not create unique index "basetest_a_pkey"
DETAIL: Key (base_ptr_id)=(73) is duplicated.
Error in migration: basetest:0002_auto__add_base__del_field_b_a_ptr__add_field_b_base_ptr__del_field_a_i
IntegrityError: could not create unique index "basetest_a_pkey"
DETAIL: Key (base_ptr_id)=(73) is duplicated.
Run Code Online (Sandbox Code Playgroud)
我应该使用什么值来使base_ptr进行此迁移?谢谢!
Ole*_*sov 12
如果base不能自己实例化,你可以使用abstract = Trueprop 轻松解决问题class Meta.
示例代码:
from django.db import models
class Base(models.Model):
name = models.CharField(max_length=10)
class Meta:
abstract = True
class A(Base):
pass
class B(Base):
title = models.CharField(max_length=10)
Run Code Online (Sandbox Code Playgroud)
Sha*_*ger 10
您可以分阶段完成此操作.
阶段1:在代码中创建"基础"模型.在A和B模型上,将base_ptr可添加为可空的FK 添加到Base(该名称base_ptr通过小写类名来生成Base,相应地调整您的名称).db_column='base_ptr'在新列上指定,因此不会_id添加后缀.不要改变父母身份:保持B孩子的状态A和A之前的状态(Base还没有儿童班).添加迁移以进行相应的数据库更改,然后运行它.
阶段2:创建数据迁移,复制相关数据.您应该将所有A数据复制到Base,删除冗余A记录(提供服务B实例的记录),并在剩余记录(两者A和B)中将ID复制到base_ptr.需要注意的是子类B使用两个表-它的id字段来自A的表,并在其自己的表有一个字段a_ptr是一个FK来A-所以如果你的值复制你的更新操作会更有效率a_ptr来base_ptr.确保在复制到表之后复制到base_ptr Base,因此不要违反FK约束.
阶段3:现在再次更改模型 - 删除显式base_ptrFK并按照您喜欢的方式更改父项,并创建第三个迁移(自动模式迁移).请注意,将父级设置为Base隐式定义不可为空的base_ptr字段,因此对于base_ptr字段,您只是将可空字段更改为不可为空,并且不需要默认值.
你仍然应该问的一个默认值a_ptr-从隐含的FK B到A当父母从改变被删除A到Base; 向后迁移需要默认值.您可以执行一些会导致向后迁移失败的操作,或者,如果您确实要支持它,请添加一个显式可a_ptr为空的内容B,就像base_ptr之前使用的列一样.然后可以在第四次迁移中删除该可空列.
| 归档时间: |
|
| 查看次数: |
2492 次 |
| 最近记录: |