Django-tables2: Meta-Optionen werden nicht vererbt.

Erstellt am 15. Juli 2012  ·  17Kommentare  ·  Quelle: jieter/django-tables2

Hi,

Ich habe folgende Tabellen:-

    class BaseTable(tables.Table):
        select_column = tables.CheckBoxColumn(verbose_name='', empty_values=('NA',))

        class Meta:
            attrs = {'class' : 'cool_table'}

    class EditableTable(BaseTable):
        edit_column = EditIconColumn(verbose_name=_('Edit'))

        def set_editable(self, flag):
            if flag:
                self.base_columns['edit_column'].visible = True
            else:
                self.base_columns['edit_column'].visible = False   

    class RoomTable(EditableTable):
        number = tables.Column()
        speciality = tables.Column()
        photo = ImageViewColumn(accessor='room_type.photo')

Wenn ich RoomTable das generierte <table> nicht das class Attribut. Ich kann dieses Attribut nur abrufen, wenn ich die Klasse Meta von BaseTable nach RoomTable verschiebe (oder kopiere).

Ist das ein Bug oder verwende ich es falsch?

docs

Alle 17 Kommentare

Danke für den Bericht, das ist ein Bug. Es steht jetzt ganz oben auf meiner Todo-Liste.

Vielen Dank.

Ich habe also fast fertig mit der Implementierung einer Lösung dafür, und dann erinnerte ich mich, dass ich für die Vererbung von Meta dem Django-Stil folgte, dh

class Meta(Parent.Meta):
    ...

Jetzt frage ich mich, ob es wirklich eine gute Idee ist, davon abzuweichen. Ich nehme an, es war sowieso schon immer inkonsistent, in der ersten Unterklasse von django_tables2.Table _muss man nicht_ class Meta(django_tables2.Tables): , aber für alle weiteren Unterklassen _mach_.

Ich nehme an, Sie könnten jedoch sagen, dass es keine django_tables2.Table.Meta API gibt und sie nur bei der ersten Unterklasse _startet_. Was ist Ihr Gefühl dazu? Wussten Sie, wie die Meta-Vererbung von Djangos Modell funktioniert und erwarten Sie, dass es hier anders ist? Oder waren Sie gegenüber Djangos API naiv und haben einfach versucht, was sich _richtig_ anfühlte?

Ich habe gerade Ihr ursprüngliches Problem erneut gelesen, und Ihr Problem scheint zu sein, dass Sie nicht einmal versuchen, Metaoptionen in Ihrer Unterklasse zu ändern, sondern nur versuchen, Unterklassen zu erstellen und Spalten hinzuzufügen.

Entschuldigung, ich verstehe nicht genau, was Sie sagen, aber ja, was ich getan habe, fühlte sich richtig an. Wie auch immer, ich bin ziemlich neu in Sachen Meta, daher ist mein Ansatz möglicherweise nicht gut.

Bradley,

Liebe die Arbeit an diesem Projekt. Ich stoße hier auf das gleiche Problem wie applegrew, und Ihr letzter Kommentar passt perfekt zu meinem Fall.

### Table Definitions ###
# parent class 
import django_tables2 as tables

# generic parent class to handle table styling
class MyAppTable(tables.Table):
    class Meta:
        attrs = {'class': 'render-table'}


# subclass in a separate app
from myapp_helpers.tables import MyAppTable
from django_tables2.utils import A
import django_tables2 as tables

class ItemTable(MyAppTable):

    address_1 = tables.Column()
    address_2 = tables.Column()
    address_3 = tables.Column()
    city = tables.Column()
    state = tables.Column()
    zipcode = tables.Column()

    # need this to fix a bug with the meta class not passing through to subclasses in django-tables2
    class Meta(MyAppTable.Meta):
        pass


## Views ##

# class based view in separate app
from django_tables2 import SingleTableView

# Parent class to make pagination the same across views
class MyAppListView(SingleTableView):

    # default of 10 rows in every table on every page
    table_pagination = {"per_page": 10 }
    template_name = 'generic_list.html'


# subclass of view in local app
class ItemListView(MyAppListView):
    model = Item
    table_class = ItemTable

Wenn die Klassen-Meta-Definition nicht in ItemTable platziert wird, werden die in der übergeordneten Klasse festgelegten Meta-Attribute nicht durchgesendet. Ich möchte, dass die gleichen Attribute an alle Tabellen in meinen Apps gesendet werden (die schließlich von MyAppTable erben).

Das Definieren der leeren Meta-Klasse in ItemTable, die von der übergeordneten Meta-Klasse (MyAppTable) erbt, funktioniert, scheint aber gegen das DRY-Prinzip zu funktionieren, obwohl es nur zwei Zeilen sind und immer noch meine Anforderung erfüllt, die CSS-Klasse nur in einer zu ändern Stelle sollte ich es brauchen. Schätze die Arbeit! Dankeschön.

Ich weiß, woher Sie kommen, und ich stimme Ihnen eher zu, tatsächlich habe ich teilweise einen Patch geschrieben, um dies zu implementieren, aber dieser Ansatz widerspricht dem Ansatz, den Django mit Modellen verfolgt. Meine derzeitige Haltung ist jedoch, dass es wichtig ist, dass die Dinge ähnlich wie bei Django funktionieren, damit die Bibliothek wie erwartet funktioniert.

Glauben Sie, dass es sich wirklich lohnt, dafür vom Standardverhalten von Django + Python zu brechen?

Nachdem ich nur etwa einen Monat lang mit Django/Python entwickelt habe, glaube ich nicht, dass ich qualifiziert bin, ein Argument für den Bruch mit der Norm vorzubringen. Ich denke aber, es gibt ein paar Möglichkeiten. Sie könnten:

a) Dokumentieren Sie die Problemumgehung wie oben beschrieben (wenn sie es noch nicht ist, habe ich sie möglicherweise übersehen). Es ist wirklich nicht so schlimm.
b) Geben Sie ein Attribut wie 'inherit_meta = False' an, das in Unterklassen überschrieben werden kann, damit Unterklassen die Metainformationen erben können. Der Standardwert wäre false, damit die Dinge nach den Django-Standards funktionieren, aber abenteuerlustigeren/fauleren Leuten wie mir würde es ermöglichen, die wiederholten Meta-Klassendefinitionen überflüssig zu machen. Das einzige Problem, das ich dabei sehe, besteht darin, einen zusätzlichen Codeblock für eine Problemumgehung beizubehalten, die möglicherweise Fehler einführen könnte (Daten sind vorhanden, wenn sie nicht erwartet werden) usw.
c) Machen Sie dieses Verhalten zum neuen Standard.

Während ich dies schreibe, kann ich bereits Szenarien in meinem Kopf sehen, in denen Vorlagenvariablen aufgrund der Tatsache überprüft werden, dass keine Vererbung stattfindet, ein Bruch auftritt und ich Stunden damit verbringe, im Code herumzustöbern, nur um herauszufinden, dass er kaputt ist, weil ich das Verhalten manuell überschreiben. Es würde auch keinem der vorhandenen Beispiele entsprechen.

Ehrlich gesagt lohnt sich der Aufwand wahrscheinlich nicht. Ich würde lieber einen zusätzlichen Hinweis zur Meta-Vererbung "gotcha" in der Dokumentation sehen, als zu versuchen, in einer Problemumgehung zu codieren, um atypisches Verhalten zu erzeugen.

Zu a) machst du es so:

class Parent(tables.Table):
    class Meta:
        foo = 1

class Child(Parent):
    class Meta(Parent.Meta):
        bar = 2

Child.Meta jetzt foo = 1 _and_ bar = 2

Ich neige dazu, zuzustimmen, dass dies mit Dokumentation behoben werden kann.

Vielen Dank. Ich hatte dies tatsächlich in meinem Beispiel basierend auf dem Beispiel von applegrew.

Hach, guter Punkt.

Ein Ärgernis bei der Problemumgehung besteht darin, dass Sie dann nichts in der Parent-Klasse überschreiben können:

class Parent(tables.Table):
    class Meta:
        attrs = {...}

class Child(Parent):
    class Meta(Parent.Meta):
         attrs = {'summary': 'A child table'}

wirft ein NameError mit name 'attrs' is not defined . Dies scheint jedoch zu funktionieren, ist aber hässlich:

class Child(Parent):
    class Meta(Parent.Meta):
        pass
     Meta.attrs['summary'] = 'A child table'

Gibt es schon eine Lösung für diesen Bug? Die obige Problemumgehung funktioniert bei mir nicht. http://stackoverflow.com/questions/21787938/inherit-and-modify-a-meta-class

Ich sehe keinen offensichtlichen Algorithmus zum Zusammenführen von zwei beliebigen class Meta . Denken Sie an die Fälle, in denen Sie einen Schlüssel zu attrs hinzufügen, einen Schlüssel aus attrs entfernen, attrs durch ein neues Diktat ersetzen usw. Vielleicht übersehe ich etwas, aber das ist es nicht für mich klar, wie du das vernünftig machen würdest.

Das Verhalten sollte dasselbe sein, als wären Sie Unterklassen models.Model Klassen.

Ich bin mir nicht sicher, ob ich dem folgen kann, was Sie sagen. Ich versuche nur, das Meta von der Elternklasse zu erben und ein paar Spalten hinzuzufügen. Ich habe den Code in der obigen SO-Frage aktualisiert, was hoffentlich etwas mehr Sinn macht.

@bradleyayers -- wenn ich deine Anfrage richtig verstehe, solltest du diesem StackOverflow-Beitrag folgen können, um Meta zu überschreiben

@pydolan Ja, überprüfen Sie http://stackoverflow.com/questions/21787938/inherit-and-modify-a-meta-class auch auf einige andere Ansätze.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen