Quindi, per un progetto Django, mi piacerebbe molto essere in grado di generare e visualizzare tabelle (non basate sui querysets) in modo dinamico senza bisogno per conoscere in anticipo il contenuto o lo schema.Problemi nel tentativo di aggiungere dinamicamente metodi alla classe Python (es. Django-tables2 'Table')
Sembra che l'app django-tables2 fornisca una buona funzionalità per il rendering delle tabelle, ma richiede che si dichiarino esplicitamente i nomi delle colonne dichiarando gli attributi su una sottoclasse Tabella definita dall'utente oppure fornire un modello per inferirne le colonne.
Vale a dire, per usare una colonna denominata "nome", faresti:
class NameTable(tables.Table):
name = tables.Column()
La classe tabelle non fornisce un metodo per aggiungere le colonne post-facto perché, dalla lettura della fonte, a quanto pare per utilizzare una metaclasse che spazza gli attributi di classe su __new__ e li blocchi.
Sembrava molto semplice metaprogramming sarebbe una soluzione elegante. Ho definito una fabbrica di base di classe che accetta i nomi di colonna sono argomenti:
def define_table(columns):
class klass(tables.Table): pass
for col in columns:
setattr(klass, col, tables.Column())
return klass
Purtroppo questo non funziona. Se corro `
x = define_table(["foo", "bar"])(data)
x.foo
x.bar
torno:
<django_tables2.columns.base.Column object at 0x7f34755af5d0>
<django_tables2.columns.base.Column object at 0x7f347577f750>
Ma se vi elenco le colonne:
print x.base_columns
mi rimetto niente cioè {}
mi rendo conto che ci sono probabilmente soluzioni più semplici (ad esempio, basta mordere il proiettile e definire ogni possibile configurazione di dati nel codice, o non usare django-tables2 e arrotolo il mio), ma ora sto trattando questo come un'opportunità per saperne di più sulla meta-programmazione, quindi mi piacerebbe davvero farlo funzionare in questo modo.
Qualche idea su cosa ho sbagliato a fare qualcosa di sbagliato? La mia teoria è che il metodo __new__ (che viene ridefinito nella tabella metaclasse utilizza) viene richiamato quando klass è definito piuttosto che quando viene istanziato, quindi nel momento in cui scrivo sugli attributi è troppo tardi. Ma questo viola la mia comprensione di quando __new__ dovrebbe accadere. Altrimenti, sto faticando a capire come il metaclass __new__ possa dire la differenza tra gli attributi definiti nel codice e quelli definiti dinamicamente.
Grazie!
Impressionante. Funziona! In alternativa, sembra che il solo fatto di eseguire 'table.base_columns [col] = col' funzioni, ma potrebbe essere una violazione di qualcosa che non vedo poiché aggira il codice di creazione della colonna. Quindi la tua soluzione è molto meglio. I futuri lettori dovrebbero anche verificare la risposta di @ BrenBarn poiché spiega perché il mio metodo stava fallendo. – rogueleaderr
@rogueleaderr contento che ha funzionato per voi. Mentre è nella tua mente, dovresti leggere i metaclassi e le varie funzioni che forniscono. Sono particolarmente utili per capire quando si gioca con Django, dato che i modelli e le forme li usano entrambi, ea volte dovrete entrare nel nocciolo della questione. –