1

How do you override a model's metaclass in Django 1.5? I was overriding the metaclass on some models inheriting from an abstract model so I could set appropriate choices. e.g.

class BaseModel(models.Model):

    field_with_choices = models.CharField(max_length=100)

    class Meta:
        abstract = True

class MyModelMetaClass(BaseModel.__metaclass__):
    def __new__(cls, *args, **kwargs):
        new_class = super(MyModelMetaClass, cls).__new__(cls, *args, **kwargs)
        field = new_class._meta.get_field('field_with_choices')
        choices = field._choices = []
        choices.extend(get_choices())
        return new_class

class MyModel(BaseModel):

    __metaclass__ = MyModelMetaClass

However, when I upgraded to Django 1.5, I now get the error:

AttributeError: type object 'BaseModel' has no attribute '__metaclass__'

How do you override a model's metaclass in 1.5, or otherwise dynamically set field attributes in model subclasses?

4

2 回答 2

5

您可以像这样使用该built-in功能type

class MyModelMetaClass(type(BaseModel)):
    def __new__(cls, *args, **kwargs):
        new_class = super(MyModelMetaClass, cls).__new__(cls, *args, **kwargs)
        field = new_class._meta.get_field('field_with_choices')
        choices = field._choices = []
        choices.extend(get_choices())
        return new_class

尽管我看到了这type(ModelBase) is type一点,但您基本上可以继承type或可能继承自Model.__metaclass__哪一个,因此模型元类架构的顶部也是ModelBase如此(当然是 :D 之前)。ModelBasetype

希望能帮助到你!

于 2013-05-14T21:10:13.900 回答
0

如果我理解正确,django 1.5 使用6进行兼容性管理。根据文档,正确的方法如下:

from six import with_metaclass

class Meta(type):
    pass

class Base(object):
    pass

class MyClass(with_metaclass(Meta, Base)):
    pass
于 2013-05-21T16:07:42.097 回答