8

したがって、Django プロジェクトの場合、コンテンツやスキーマを事前に知る必要なく、(クエリセットに基づいていない)テーブルを動的に生成および表示できるようにしたいと考えています。

django-tables2アプリはテーブルをレンダリングするための優れた機能を提供しているように見えますが、カスタム定義の Table サブクラスで属性を宣言して列名を明示的に宣言するか、列を推測するためのモデルを提供する必要があります。

つまり、「name」という名前の列を使用するには、次のようにします。

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

ソースを読むと、 __new__ のクラス属性をスイープしてロックするメタクラスを使用しているように見えるため、Tables クラスは事後的に列を追加する方法を提供しません。

非常に単純なメタプログラミングが洗練されたソリューションになるように思えました。列名を引数として受け入れる基本的なクラス ファクトリを定義しました。

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__ メソッド (テーブルが使用するメタクラスで再定義されます) は、インスタンス化されたときではなく、クラスが定義されたときに呼び出されるため、属性を追加するまでには手遅れです。しかし、それは __new__ がいつ起こるべきかについての私の理解に違反しています。それ以外の場合、メタクラス __new__ がコード内で定義された属性と動的に定義された属性の違いをどのように伝えることができるかを理解するのに苦労しています。

ありがとう!

4

2 に答える 2

6

ここでは正しい方向に進んでいますが、必要最低限​​のクラスを作成してそれに属性を追加する代わりに、type()組み込み関数を使用する必要があります。それがあなたが試みているように機能しない理由は、メタクラスがすでにその機能を果たしているからです。

を使用type()すると、基本クラスを設定しながら、独自の属性を使用して新しいクラスを作成できます。意味-クラスの青写真として必要なフィールドを記述し、Table定義の後にsメタクラスが引き継ぐことができるようにします。

type()djangoでの使用例を次に示します。私はこれを自分のプロジェクトに使用しましたが(若干のバリエーションはあります)、すでにほぼそこにいることを考えると、開始するのに最適な場所になるはずです。

def define_table(columns):
    attrs = dict((c, tables.Column()) for c in columns)
    klass = type('DynamicTable', (tables.Table,), attrs)
    return klass
于 2013-01-03T07:15:28.237 に答える
1

__new__「通常の」クラスのと__new__メタクラスのを混同しています。お気づきのように、メソッドはそのメタクラスTable依存しています。メタクラスは、クラスが定義されたときに実際に呼び出されます。クラス自体はメタクラスのインスタンスであるため、クラスを定義するとメタクラスがインスタンス化されます。(この場合、はのインスタンスです。)したがって、クラスが定義されるまでには、手遅れになります。__new__TableDeclarativeColumnMetaClass

考えられる解決策の1つは、何らかのメソッドなどTableを持つサブクラスを作成することです。refreshColumnsからのコードを適応させて、DeclarativeColumnMetaclass.__new__本質的refreshColumnsに同じ魔法を再び実行させることができます。refreshColumns()次に、新しいクラスを呼び出すことができます。

于 2013-01-03T07:16:58.613 に答える