尝试向 Python 类动态添加方法时遇到问题(即 django-tables2 'Table')

2023-11-21

因此,对于 Django 项目,我真的希望能够生成并显示表格(not基于查询集)动态地进行,无需事先了解内容或模式。

它看起来像django-tables2app 提供了很好的渲染表的功能,但它要求您通过在自定义定义的 Table 子类上声明属性来显式声明列名称,或者提供一个模型来推断列。

即,要使用名为“name”的列,您需要执行以下操作:

class NameTable(tables.Table):
   name = tables.Column()

Tables 类没有提供事后添加列的方法,因为从阅读源代码来看,它似乎使用了一个元类来扫描 __new__ 上的类属性并将它们锁定。

看起来非常简单的元编程将是一个优雅的解决方案。我定义了一个接受列名作为参数的基本类工厂:

def define_table(columns):
    class klass(tables.Table): pass              
    for col in columns:
        setattr(klass, col, tables.Column())
    return klass

遗憾的是这不起作用。如果我运行`

x = define_table(["foo", "bar"])(data)
x.foo
x.bar

我回来了:

<django_tables2.columns.base.Column object at 0x7f34755af5d0>
<django_tables2.columns.base.Column object at 0x7f347577f750>

但如果我列出这些列:

print x.base_columns

我什么也没得到,即 {}

我意识到可能有更简单的解决方案(例如,硬着头皮在代码中定义每个可能的数据配置,或者不使用 django-tables2 并推出我自己的),但我现在将此视为了解更多信息的机会元编程,所以我真的很想让它以这种方式工作。

知道我做错了什么吗?我的理论是, __new__ 方法(​​在 Table 使用的元类中重新定义)是在定义 klass 时而不是在实例化它时调用的,所以当我添加属性时已经太晚了。但这违反了我对 __new__ 何时应该发生的理解。否则,我很难理解元类 __new__ 如何区分代码中定义的属性与动态定义的属性之间的区别。

Thanks!


您在这里的方向是正确的,但是您应该使用type()内置功能。它没有按照您尝试的方式工作的原因是因为元类已经完成了它的工作。

Using type()允许您在设置基类的同时使用自己的属性构造一个新类。含义 - 你可以描述你想要的字段作为你的类的蓝图,允许Tables 元类在您的定义之后接管。

这是一个例子使用的type()与 Django 一起。我自己在自己的项目中使用了这个(有一些细微的变化),但考虑到您已经快要实现了,它应该为您提供一个很好的起点。

def define_table(columns):
    attrs = dict((c, tables.Column()) for c in columns)
    klass = type('DynamicTable', (tables.Table,), attrs)
    return klass
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

尝试向 Python 类动态添加方法时遇到问题(即 django-tables2 'Table') 的相关文章

随机推荐