Django - 在__init__中添加模型字段验证器

时间:2014-04-10 10:40:02

标签: django django-admin django-models

我需要通过抽象类添加字段验证器。

我正在使用的代码假设从这个抽象类继承的每个类都有一个字段name,但不幸的是,这个字段本身并没有在抽象类中定义。

所以我尝试了以下内容,但我不确定在self._meta.fields找到该字段的好方法是什么,因为这是一个列表.. ??

class AbsClass(models.Model):
    class Meta:
        abstract = True
    def __init__(self, *args, **kw):
        super(AbsClass, self).__init__(*args, **kw)
        name_field = [f for f in self._meta.fields if f.name == 'name'][0]  # Is there another way?
        name_field.validators.append(my_validator)

2 个答案:

答案 0 :(得分:2)

您需要Options.get_field

...
name_field = self._meta.get_field('name')
name_field.validators.append(my_validator)
...

然而,您的方法似乎并不是一个好主意:模型的所有实例之间共享模型的字段实例(它们的引用存储在类属性中,而不是实例属性中)。这意味着每次实例化模型的对象时,您都会将另一个副本my_validator添加到字段的验证器中,因为您将它添加到同一个字段实例中。

您可以为您的抽象基类实现元类,并在编译时添加验证器,而不是在运行时篡改字段实例,这与此类似(未经测试):

from django.utils.six import with_metaclass
from django.db.models.base import ModelBase

# inherit from Django's model metaclass
class AbsClassMeta(ModelBase):

    def __new__(cls, name, bases, attrs):
        if 'name' in attrs:
            attrs['name'].validators.append(my_validator)
        elif name != 'AbsClass':
            # is it an error to not have a "name" field in your subclasses?
            # handle situation appropriately
        return super(AbsClassMeta, cls).__new__(cls, name, bases, attrs)

class AbsClass(with_metaclass(AbsClassMeta, models.Model)):
    ...

请注意,您的AbsClass类本身也将使用此元类创建。如果您决定在AbsClassMeta.__new__中如果该类没有name字段时抛出异常,则需要考虑这一点,因为您的AbsClass类没有{ {1}}字段。

答案 1 :(得分:0)

在Django 2.x中

代替

name_field = self._meta.get_field('name')
name_field.validators.append(my_validator)

您可以这样做:

name_field = self.fields['name']
password_field.validators.append(my_validator)