python - 返回修改后的类和使用 type() 的区别

标签 python django class types

我想这更像是一个 python 问题而不是 django 问题,但我无法在其他任何地方复制这种行为,所以我将使用无法按预期工作的确切代码。

当我发现这个工厂函数片段时,我正在 django 中处理一些动态表单:

def get_employee_form(employee):
    """Return the form for a specific Board."""
    employee_fields = EmployeeFieldModel.objects.filter(employee = employee).order_by   ('order')
    class EmployeeForm(forms.Form):
        def __init__(self, *args, **kwargs):
            forms.Form.__init__(self, *args, **kwargs)
            self.employee = employee
        def save(self):
            "Do the save"
    for field in employee_fields:
        setattr(EmployeeForm, field.name, copy(type_mapping[field.type]))
    return type('EmployeeForm', (forms.Form, ), dict(EmployeeForm.__dict__))

[来自:http://uswaretech.com/blog/2008/10/dynamic-forms-with-django/ ]

有一件事我不明白,为什么返回修改后的 EmployeeForm 不起作用? 我的意思是这样的:

def get_employee_form(employee):
    #[...]same function body as before

    for field in employee_fields:
        setattr(EmployeeForm, field.name, copy(type_mapping[field.type]))
    return EmployeeForm

当我尝试返回修改后的类时,django 忽略了我的附加字段,但返回 type() 的结果完美无缺。

最佳答案

Lennart 的假设是正确的:元类确实是罪魁祸首。不用猜,看the sources就知道了: 元类是 DeclarativeFieldsMetaclass 当前位于该文件的第 53 行,并根据类在创建时具有的属性添加属性 base_fields 和可能的 media时间。在第 329 行你看到:

class Form(BaseForm):
    "A collection of Fields, plus their associated data."
    # This is a separate class from BaseForm in order to abstract the way
    # self.fields is specified. This class (Form) is the one that does the
    # fancy metaclass stuff purely for the semantic sugar -- it allows one
    # to define a form using declarative syntax.
    # BaseForm itself has no way of designating self.fields.
    __metaclass__ = DeclarativeFieldsMetaclass

这意味着在创建具有基础 type 的新类时存在一些脆弱性——所提供的黑魔法可能会也可能不会成功!一种更可靠的方法是使用 EmployeeForm 的类型,它将选取可能涉及的任何元类——即:

return type(EmployeeForm)('EmployeeForm', (forms.Form, ), EmployeeForm.__dict__)

(不需要复制那个 __dict__,顺便说一句)。区别很细微但很重要:我们没有直接使用 type 的 3-args 形式,而是使用 1-arg 形式来获取表单类的类型(即元类),然后以 3-args 形式调用该元类。

确实是黑魔法,但这就是框架的缺点,这些框架使用“纯粹为了语义糖的花哨的元类”&c:只要你想做框架支持的事情,你就在三叶草中,但是哪怕是一点点摆脱这种支持都可能需要抵消巫术(这在某种程度上解释了为什么我经常宁愿使用轻量级、透明的设置,比如 werkzeug,而不是像 Rails 或Django 做:我精通深黑魔法并不意味着我很高兴必须在普通生产代码中使用它……但是,那是另一个讨论;-)。

关于python - 返回修改后的类和使用 type() 的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1251294/

相关文章:

c++ - 将类声明为整数

css - css 中的 2 类样式声明不起作用

python - 为什么我不能继承 Enum 的子类?

python - Jedi - Python 自动完成(提示)不显示方法或建议

django - 如何由用户查询 Django 中的模型

python - Django - 如何保存我的散列密码

Python 的 Min() 用于自定义类(二叉搜索树)

python - 计算在某个范围内具有特定值的键的数量

python - 属性错误: 'DeferredAttribute' object has no attribute 'objects'

javascript - 使用 Mootools 理解类