定义abstact django模型字段

时间:2018-08-30 09:58:33

标签: django django-models

我需要创建一个抽象的Django模型,并且要强制执行所有模型-继承者重新定义该字段。 我已经尝试过了,但是有一个例外:

from django.db import models


class AbstractField(models.Field):
    description = "Abstract Field"

    def __init__(self):
        raise NotImplementedError("You have to redefine your field in model.")


class MyAbstractModel(models.Model):
    id = models.AutoField(primary_key=True)
    redefine_me_please = AbstractField()

    class Meta:
        abstract = True


class MyNotAbstractModel(MyAbstractModel):
    redefine_me_please = models.CharField(verbose_name='Name', max_length=255)

NotImplementedError动作中的makemigrations是一个例外。
知道如何模仿抽象字段吗?

2 个答案:

答案 0 :(得分:1)

这不能以这种方式工作-定义类时会实例化模型字段,因此使用此实现,您将永远无法仅导入模型文件。

正确的解决方案是使用自定义元类-它必须从Django自己的模型元类继承。这是一个使用Python2语法的示例实现(您肯定必须以某种方式对其进行改进),我让您检查文档中是否存在Python3的语法差异。

from django.db.models.base import ModelBase

class MyAbstractField(object):
    pass

class MyAbstractModelType(ModelBase):
    def __new__(metacls, name, bases, attrs):
        must_check = True
        djmeta = attrs.get("Meta", None)
        if djmeta and getattr(djmeta, "abstract", False):
            must_check = False
        if must_check:          
            for attrname, value in attrs.items():
                if isinstance(value, MyAbstractField):
                    raise TypeError("Class %s must redefine %s" % (name, attrname))

        return ModelBase.__new__(metacls, name, bases, attrs)

class MyAbstractBase(models.Model):
    __metaclass__ = MyAbstractModelType

    foo = MyAbstractField()

    class Meta:
        abstract = True

class CorrectConcreteModel(MyAbstractBase):
    foo = models.IntegerField()

class IncorrectConcreteModel(MyAbstractBase):
    pass

使用此代码,未重新定义foo的具体MyAbstractBase子类(对于Django的“具体模型子类”的定义)将在导入时引发TypeError,使问题立即对编码人员显而易见。可能的改进方法是检查foo是否是正确的模型字段(除了MyAbstractField外,其他任何ATM都将被接受)。

答案 1 :(得分:0)

建议您使用OneToOne关系实现继承。

您想要做的可能是:https://docs.djangoproject.com/en/2.1/topics/db/models/#abstract-base-classes