我需要创建一个抽象的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
是一个例外。
知道如何模仿抽象字段吗?
答案 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