Django-我可以为特定子模型更改抽象基础模型中定义的字段的构造吗?

Django-我可以为特定子模型更改抽象基础模型中定义的字段的构造吗?,django,django-models,factory,Django,Django Models,Factory,为了序列化的目的,我在所有模型中添加了一个slug,因此我定义了一个抽象基类,它使用来自的AutoSlugField 我还定义了一个自定义管理器和一个natural_key方法,目前我有大约20个子类,因此,除了定义字段的单行之外,使用抽象基础模型还有一些好处 但是,我希望能够切换一些默认参数,以便为一些子模型初始化AutoSlugField,同时仍然能够利用抽象基类。例如,我希望他们中的一些人使用populate\u from选项,从他们的特定模型中指定字段,而其他人使用db\u index=

为了序列化的目的,我在所有模型中添加了一个slug,因此我定义了一个抽象基类,它使用来自的AutoSlugField

我还定义了一个自定义管理器和一个natural_key方法,目前我有大约20个子类,因此,除了定义字段的单行之外,使用抽象基础模型还有一些好处

但是,我希望能够切换一些默认参数,以便为一些子模型初始化
AutoSlugField
,同时仍然能够利用抽象基类。例如,我希望他们中的一些人使用
populate\u from
选项,从他们的特定模型中指定字段,而其他人使用
db\u index=True
而不是我的默认值(
False


我开始尝试用一个自定义元类来实现这一点,利用每个子模型的内部元类中定义的自定义选项,但这已经成了老鼠窝。我愿意接受有关该方法的指导或任何其他建议。

一种解决方案是动态构造抽象基类。例如:

def get_slugger_model(**slug_kwargs):
    defaults = {
        'unique': True,
        'db_index': False
    }
    defaults.update(slug_kwargs)

    class MySluggerModel(models.Model):
        slug = AutoSlugField(**defaults)

        class Meta:
            abstract = True

    return MySluggerModel


class MyModel(get_slugger_model()):
    pass


class MyModel2(get_slugger_model(populate_from='name')):
    name = models.CharField(max_length=20)

更新:我一开始采用了以下丑陋的解决方案,后来改用了丹尼尔的解决方案,但事实并非如此。我把我的留在这里作为参考

这是我的元类捕鼠器,似乎正在工作(还没有广泛的测试)

SlugModel
现在基本上是这样的:

class SluggerModel(models.Model):
    __metaclass__ = SluggerMetaclass
    objects = SluggerManager()
    # I don't define the AutoSlugField here because the metaclass will add it to the child class.
    class Meta:
        abstract = True
我可以通过以下方式达到预期效果:

class SomeModel(SluggerModel, BaseModel):
    name = CharField(...)
    class Meta:
        slug_from = 'name'
        slug_db_index = True
对于具有多个抽象父模型的模型,我必须将SlugerModel放在继承列表的第一位,否则其他父模型将无法拾取字段,验证将失败;然而,我无法解释原因


我想我可以把这个问题作为我自己问题的答案,因为它是有效的,但我希望有一个更好的方法,因为它有点丑陋的一面。再说一次,hax就是hax,那么你能做些什么,所以也许这就是答案。

啊。基地模型工厂!我喜欢。我真的没有考虑过这种模式。比我的元类Thingeglad更清晰易读。伟大的创业理念,顺便说一句!
class SluggerModel(models.Model):
    __metaclass__ = SluggerMetaclass
    objects = SluggerManager()
    # I don't define the AutoSlugField here because the metaclass will add it to the child class.
    class Meta:
        abstract = True
class SomeModel(SluggerModel, BaseModel):
    name = CharField(...)
    class Meta:
        slug_from = 'name'
        slug_db_index = True