Django mptt数据库迁移报错

Django mptt database migration error

我正在尝试让 mptt 与我当前的项目一起使用,但在数据库迁移方面遇到问题。

这是我的模型

from django.db import models
from mptt.models import MPTTModel, TreeForeignKey

class Section(MPTTModel):
    name = models.CharField(max_length=50, unique=True)
    parent = TreeForeignKey('self', null=True, blank=True, related_name='children', db_index=True)

    class MPTTMeta:
        order_insertion_by = ['name']

并在命令行中输入 运行:

sudo python manage.py makemigrations core

但似乎出现了与级别字段相关的错误

You are trying to add a non-nullable field 'level' to section without a default; we can't do that (the database needs something to populate existing rows).
Please select a fix:
 1) Provide a one-off default now (will be set on all existing rows)
 2) Quit, and let me add a default in models.py
Select an option:

我该怎么办?

'Level' 由 MPTTModel 自动添加以表示树中特定节点的 'depth'。如果您还没有创建树结构,那么选择选项 1 并将所有内容默认设置为 0 级(根)应该是安全的。如果您还没有设置树结构,这应该没问题,并且应该在您稍后使用树时进行调整。

如果您已经有了一个树结构并且需要在您的数据中反映出来,您仍然需要这样做,但是您需要在它后面加上一个(可能是手写的)data migration设置正确的值。

--- 2022 年更新 ---

据我所知,您可以将 levellftrghttree_id:

的所有内容都设置为 0

例如:

You are trying to add a non-nullable field 'level' to section without a default; we can't do that (the database needs something to populate existing rows).
Please select a fix:
 1) Provide a one-off default now (will be set on all existing rows)
 2) Quit, and let me add a default in models.py
Select an option:

将所有值设置为零并迁移后,树将如下所示:

{
  "id": 1,
  "name":"first test tree",
  "lft": 0,
  "rght": 0,
  "tree_id": 0,
  "level": 0,
  "parent": null
}

然后你需要进入 shell 并重建所有树:

Section.objects.rebuild()

完成重建命令后,您的树将设置为正常状态,能够创建新的子树:

{
   "id": 1,
   "name": "first test tree",
   "lft": 1,
   "rght": 2,
   "tree_id": 1,
   "level": 0,
   "parent": null
}

其他方法:

您还可以在保存后在模型中添加 rebuild() 命令;非常适合那些无法访问数据库或生产终端的人:

from django.db import models
from mptt.models import MPTTModel, TreeForeignKey

class Section(MPTTModel):
    name = models.CharField(max_length=50, unique=True)
    parent = TreeForeignKey('self', null=True, blank=True, related_name='children', db_index=True)

    class MPTTMeta:
        order_insertion_by = ['name']

    def save(self, *args, **kwargs):
        # before save
        super(Section, self).save(*args, **kwargs)
        # after save...
        try:
            # get all objects from the Section table.
            trees = Section.objects.all()
            # loops through all values.
            for tree in trees:
                # checks if there is default=0 and if yes rebuild the trees.
                if tree.lft or tree.rght or tree.tree_id == 0:
                    Section.objects.rebuild() 
        except Exception as e:
            print(e)
            pass