我想这更像是一个 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/