Django 1 到 Django 2 on_delete 错误

Django 1 to Django 2 on_delete error

我相信这个工作流程是为以前的 Django 版本创建的。现在,当我尝试升级它时,出现添加 on_delete 的错误。这是我所做的,但它仍然无法正常工作,我想知道我做错了什么。

原创

class Task(AbstractEntity):
    request = ForeignKey(Request, related_name='tasks')   
    assignee = ForeignKey(Group)    
    updated_by = ForeignKey(User)    
    activity_ref = CharField(max_length=100)    
    status = CharField(verbose_name="Status", max_length=30, choices=TASK_STATUS)

我的版本

class Task(models.AbstractEntity):
    request = models.ForeignKey(Request, related_name='tasks', on_delete=models.CASCADE)
    assignee = ForeignKey(Group)
    updated_by = ForeignKey(User)
    activity_ref = CharField(max_length=100)
    status = CharField(verbose_name="Status", max_length=30, choices=TASK_STATUS)

然后我收到另一个错误,指出模型未定义。

根据 Django 2.0 docs (and also the release notes) 所有 Foreignkey 字段现在都有一个必需的 on_delete 参数。

您模型的字段中似乎缺少它。发行说明还建议查看您的迁移:

The on_delete argument for ForeignKey and OneToOneField is now required in models and migrations. Consider squashing migrations so that you have fewer of them to update.

有一个解决方法。

如果你有很多很多 table 需要在使用外键或一对一键的地方添加“on_delete”参数..然后遍历所有模型添加 on_delete 参数会很忙。 您可以执行外键的猴子补丁来实现您的目标。

在您的项目设置文件夹中添加以下猴子补丁文件:

monkey_patches.py

from django.db import models
from django.db.models import ForeignKey
from django.db import models
from django.db.models import ForeignKey, OneToOneRel
from django.db.models.fields.related_descriptors import ReverseOneToOneDescriptor, ForwardOneToOneDescriptor
from django.utils.translation import gettext_lazy as _


class ForeignKeyMonkeyPatch(ForeignKey):
    def __init__(self, to, on_delete=None, *args, **kwargs):
        super().__init__(to, on_delete, *args, **kwargs)


class OneToOneFieldMonkeyPatch(ForeignKeyMonkeyPatch):
    many_to_many = False
    many_to_one = False
    one_to_many = False
    one_to_one = True

    related_accessor_class = ReverseOneToOneDescriptor
    forward_related_accessor_class = ForwardOneToOneDescriptor
    rel_class = OneToOneRel

    description = _("One-to-one relationship")

    def __init__(self, to, on_delete=None, *args, **kwargs):
        kwargs['unique'] = True
        super().__init__(to, on_delete, *args, **kwargs)

    def deconstruct(self):
        name, path, args, kwargs = super().deconstruct()
        if "unique" in kwargs:
            del kwargs['unique']
        return name, path, args, kwargs

    def formfield(self, **kwargs):
        if self.remote_field.parent_link:
            return None
        return super().formfield(**kwargs)

    def save_form_data(self, instance, data):
        if isinstance(data, self.remote_field.model):
            setattr(instance, self.name, data)
        else:
            setattr(instance, self.attname, data)

    def _check_unique(self, **kwargs):
        # Override ForeignKey since check isn't applicable here.
        return []




setattr(models, 'ForeignKey', ForeignKeyMonkeyPatch)
setattr(models, 'OneToOneField', OneToOneFieldMonkeyPatch)

现在,在您的项目设置中调用此文件...

from .monkey_patches import *

上面的代码将用我们的猴子补丁 类 重置 ForeignKeyOneToOneField,从而设置 on_delete默认为None

P.S。 (你甚至可以创建一个应用程序(命名为“monkey_patches”或任何你想要的..)并在 models.py 中添加上面的代码)