2013-01-03 2 views
6

의 메소드를 추가하는 데 문제가 있습니다. 장고 프로젝트의 경우, 필요없이 미리 내용이나 스키마를 알아야합니다.동적으로 (즉, django-tables2 'Table')

django-tables2 앱이 테이블 렌더링에 유용한 기능을 제공하지만 사용자 정의 테이블 하위 클래스에서 속성을 선언하여 명시 적으로 열 이름을 선언하거나 열을 추론 할 모델을 제공해야합니다.

즉, "이름"라는 이름의 열을 사용하는, 당신이 할 것 :

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

테이블 클래스는 소스를 읽고, 그것은 보인다 때문에 이후 사실상 열을 추가하는 방법을 제공하지 않습니다 __new__에 클래스 속성을 소탕하고 그들을 잠그는 메타 클래스를 사용합니다.

을 우아한 해결책이 될 것입니다 매우 간단한 메타 프로그래밍처럼 보였다. 열 이름을 받아들이는 기본 클래스 팩터 리를 정의했습니다.

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

슬프게도 이것은 작동하지 않습니다.

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

을하지만 열을 게시하면 : 나는`

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

을 실행하면 내가 다시 얻을

print x.base_columns 

나는 즉, {}

나는 것을 깨닫게 다시 아무것도 얻을 아마도 간단한 해결책이있을 수 있습니다 (예 : 총알을 물고 모든 가능한 데이터 구성을 코드에 정의하거나 django-tables2를 사용하지 마십시오. 내 자신을 롤업해라.)하지만 지금은 이것을 메타 프로그래밍에 대해 더 많이 배울 수있는 기회로 생각하고있다. 그래서 나는이 방법을이 방법으로 만들고 싶다.

내가 잘못하고 틀렸다 어떤 생각? 내 이론은 인스턴스화 될 때가 아니라 klass가 정의 될 때 __new__ 메쏘드 (메타 클래스 테이블에서 재정의 됨)가 호출되기 때문에 너무 늦은 속성을 가감 할 때가된다. 그러나 그것은 __new__이 언제 일어나야하는지에 대한 나의 이해를 위배한다. 그렇지 않으면, 나는 __new__ 메타 클래스가 정의 된 코드 속성과 동적으로 정의 된 속성의 차이점을 어떻게 알 수 있는지 이해하기 위해 애 쓰고 있습니다.

감사합니다.

답변

4

여기 올바른 길을 가고 있지만 베어 본 클래스를 만들고 속성을 추가하는 대신 type() 내장 함수를 사용해야합니다. 노력하는 방식대로 작동하지 않는 이유는 메타 클래스가 이미 작업을 완료했기 때문입니다. 기본 클래스를 설정하는 동안 type()를 사용

, 당신은 당신의 자신의 속성을 가지는 새로운 클래스를 구성 할 수 있습니다. 의미 - 클래스의 청사진으로 원하는 필드를 설명하고, 정의 후에 Table의 메타 클래스를 인계받을 수 있습니다. 장고와 type()를 사용

Here's an example. 나는이 프로젝트를 약간의 변형으로 자신의 프로젝트에 사용했지만 이미 거의 다 왔다고 생각하면 시작할 수있는 좋은 곳을 제공해야한다.

def define_table(columns): 
    attrs = dict((c, tables.Column()) for c in columns) 
    klass = type('DynamicTable', (tables.Table,), attrs) 
    return klass 
+0

굉장합니다. 이 작품! 또는,'table.base_columns [col] = col' 만 실행하는 것처럼 보이지만 열 생성 코드를 우회하기 때문에 보이지 않는 것을 깨뜨릴 수 있습니다. 그래서 당신의 솔루션이 훨씬 낫습니다. 미래의 독자는 @ BrenBarn의 대답을 확인해야합니다. 왜냐하면 내 방법이 실패한 이유를 설명하기 때문입니다. – rogueleaderr

+2

@rogueleaderr 기쁜 당신을 위해. 그것이 마음에 들었을 때, 당신은 메타 클래스와 그들이 제공하는 다양한 기능에 대한 정보를 읽어야합니다. Django와 함께 놀 때, Models and Forms에서 둘 다 사용하기 때문에 이해하는 것이 특히 유용합니다. 언젠가는 당신은 핵심에 빠지게 될 것입니다. –

1

당신은 메타 클래스의 __new__으로 "일반"클래스의 __new__을 혼동하고 있습니다. 참고로, Table메타 클래스에서 __new__ 메서드를 사용합니다. 메타 클래스는 실제로 클래스가 정의 될 때 호출됩니다. 클래스 자체는 메타 클래스의 인스턴스이므로 클래스를 정의하면 메타 클래스가 인스턴스화됩니다. 이 경우, TableDeclarativeColumnMetaClass의 인스턴스입니다. 따라서 클래스가 정의 될 때까지는 너무 늦었습니다.

가능한 해결책 중 하나는 refreshColumns 등의 Table 하위 클래스를 작성하는 것입니다. DeclarativeColumnMetaclass.__new__에서 코드를 적용하여 본질적으로 refreshColumns을 다시 만들 수 있습니다. 그런 다음 새 수업에 refreshColumns()라고 전화 할 수 있습니다.

+0

답변 해 주셔서 감사합니다! 조쉬의 대답은 좀 더 우아하다고 생각합니다. 그러나 당신의 대답은 왜 제 방법이 실패했는지 설명하는 데 도움이됩니다. – rogueleaderr