在 Django 中从 class 外部使用 super() (或替代它,如果有的话)

Using super() from outside a class in Django (or alternative to it, if any)

以下我使用 Python 2.7 / Django 1.5.

我正在尝试重构一些使用自定义验证程序覆盖 Django 表单的 clean() 方法的生产代码。它在多个表单中重复出现,因此我们想将其抽象为一个外部函数,我们可以在表单中调用它。

假设我有以下内容,

# ... imports ...

class MyProperties(models.Model):
    label = models.CharField(max_length=100, blank=True, null=True, verbose_name=u'label'

    def __unicode__(self):
        return self.label

class MyForm(forms.ModelForm):
    choices = forms.ModelChoiceField(required=False, ...)

    class Meta:
        model = MyProperties

    def __init__(self, *args, **kwargs):
        super(MyForm, self).__init__(*args, **kwargs)

    def clean(self):
        return my_custom_clean_function(self)

def my_custom_clean_function(form_instance):
    cleaned_data = super(type(form_instance), form_instance).clean() ## DOES NOT WORK

    # other validation routines
    return cleaned_data

从 class 外部从 my_custom_clean_function 调用 super 会导致超过最大递归深度(只是调用 form_instance class 中的 clean() 方法,调用自定义函数等...

创建 ModelForm 的临时实例并调用它的 clean 方法似乎不起作用,因为它会有 none 个字段。

有什么方法可以按惯用方式执行此操作,还是我最好从表单 class 内部调用父 clean method(),然后将该数据传递给我的自定义方法以进行进一步验证?

你的super(type(instance), instance).clean()也可以;除非您进一步对表单进行子类化,否则 type(instance) 将是传入的错误对象。

或者在方法中使用super() 并将结果传递给:

class MyForm(forms.ModelForm):
    # ...

    def clean(self):
        return my_custom_clean_function(super(MyForm, form_instance).clean())

def my_custom_clean_function(cleaned_data):    
    # other validation routines
    return cleaned_data

或者你可以把它做成一个 mixin:

class SharedCleanupMixin:
    def clean(self):
        cleaned_data = super(SharedCleanupMixin, self).clean()
        # other validation routines
        return cleaned_data

并在您的表单中使用它:

class MyForm(forms.ModelForm, SharedCleanupMixin):
    # ...