Django-tables2: As opções meta não são herdadas.

Criado em 15 jul. 2012  ·  17Comentários  ·  Fonte: jieter/django-tables2

Oi,

Eu tenho as seguintes tabelas: -

    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')

Quando eu renderizo RoomTable o <table> gerado não tem o atributo class . Posso obter esse atributo apenas quando movo (ou copio) a classe Meta de BaseTable para RoomTable .

Isso é um bug ou estou usando incorretamente?

docs

Todos 17 comentários

Obrigado pelo relatório, este é um bug. Agora está no topo da minha lista de tarefas.

Obrigado.

Eu quase terminei de implementar uma solução para isso, e então me lembrei que para Meta herança eu estava seguindo o estilo Django, ou seja,

class Meta(Parent.Meta):
    ...

Portanto, agora estou começando a me perguntar se é realmente uma boa ideia me desviar disso. Suponho que sempre foi inconsistente de qualquer maneira, na primeira subclasse de django_tables2.Table você _não_ precisa fazer class Meta(django_tables2.Tables): , mas para quaisquer outras subclasses você _faça_.

Suponho que você possa dizer que não há django_tables2.Table.Meta API, e ela apenas _inicia_ na primeira subclasse. Qual é o seu sentimento sobre isso? Você sabia como a Meta-herança do modelo do Django funciona e esperava que fosse diferente aqui? Ou você foi ingênuo para a API do Django e então tentou o que parecia _certo_?

Acabei de reler seu problema original, e seu problema parece ser que você nem mesmo está tentando alterar as metaopções em sua subclasse, está apenas tentando criar uma subclasse e adicionar colunas.

Desculpe, não entendi claramente o que você está dizendo, mas sim, o que eu fiz pareceu certo. De qualquer forma, eu sou muito novo em Meta stuff, então minha abordagem pode não ser boa.

Bradley,

Amei o trabalho neste projeto. Estou tendo o mesmo problema que o applegrew aqui, e seu último comentário corresponde perfeitamente ao meu caso.

### 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

Se a definição da classe Meta não for colocada em ItemTable, os meta atributos definidos na classe pai não serão enviados. Eu gostaria de ter os mesmos atributos enviados para todas as tabelas em meus aplicativos (que eventualmente herdam de MyAppTable)

Definir a classe Meta vazia em ItemTable que herda da classe Meta pai (MyAppTable) funciona, mas parece funcionar contra o princípio DRY, embora tenha apenas duas linhas e ainda atenda ao meu requisito de precisar apenas alterar a classe CSS em uma local que eu preciso. Aprecie o trabalho! Obrigada.

Eu sei de onde você está vindo e tendo a concordar com você, na verdade eu escrevi parcialmente um patch para implementar isso, no entanto, essa abordagem contradiz a abordagem do Django com os modelos. Minha posição atual, entretanto, é que fazer as coisas funcionarem de maneira semelhante ao Django é importante para que a biblioteca funcione conforme o esperado.

Você acha que realmente vale a pena quebrar o comportamento padrão do Django + Python para isso?

Tendo desenvolvido usando Django / Python por cerca de um mês, não acho que estou qualificado para argumentar contra a quebra da norma. Suponho que existem algumas opções. Você poderia:

a) Documente a solução alternativa conforme detalhado acima (se ainda não estiver, eu posso ter esquecido). Realmente não é tão terrível.
b) Forneça um atributo como 'inherit_meta = False' que pode ser sobrescrito nas subclasses para permitir que as subclasses herdem as metainformações. O padrão seria falso para manter as coisas funcionando de acordo com os padrões do Django, mas permitiria que pessoas mais aventureiras / preguiçosas como eu eliminassem a necessidade de definições repetidas de classe Meta. O único problema que vejo com isso é manter um pedaço extra de código para uma solução alternativa que poderia potencialmente introduzir bugs (dados presentes quando não esperados), etc.
c) Torne este comportamento o novo padrão.

Mesmo enquanto escrevo isso, já posso ver cenários em minha cabeça onde as variáveis ​​de modelo são verificadas com base no fato de que a herança não ocorre, a quebra ocorre e eu passo horas vasculhando o código apenas para descobrir que ele quebrou porque eu anulou o comportamento manualmente. Também não corresponderia a nenhum dos exemplos existentes.

Francamente, provavelmente não vale a pena o esforço. Eu preferiria ver uma nota extra sobre a meta-herança 'pegadinha' na documentação do que tentar codificar uma solução alternativa para gerar um comportamento atípico.

Em relação a a), você faz assim:

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

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

Child.Meta agora tem foo = 1 _and_ bar = 2

Eu tendo a concordar que isso pode ser corrigido com documentação.

Obrigado. Na verdade, eu tinha isso no meu exemplo baseado no exemplo do applegrew.

Doh, bom ponto.

Um aborrecimento com a solução alternativa é que você não pode então substituir algo na classe Pai:

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

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

levanta NameError com name 'attrs' is not defined . Isso, no entanto, parece funcionar, mas é feio:

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

Já existe uma solução para esse bug? A solução alternativa acima não funciona para mim. http://stackoverflow.com/questions/21787938/inherit-and-modify-a-meta-class

Não vejo um algoritmo óbvio para mesclar dois class Meta arbitrários. Pense nos casos para adicionar uma chave a attrs , remover uma chave de attrs , substituir attrs por um novo dicionário, etc. Talvez eu esteja faltando alguma coisa, mas não está óbvio para mim como você faria isso de uma maneira sã.

O comportamento deve ser o mesmo que se você fosse subclasses de models.Model classes.

Não tenho certeza se entendi o que você está dizendo. Estou apenas tentando herdar o meta da classe pai e adicionar algumas colunas. Eu atualizei o código na pergunta do SO acima, o que espero que faça um pouco mais de sentido.

@bradleyayers - se estou entendendo sua solicitação corretamente, você deve conseguir seguir esta postagem StackOverflow para substituir o Meta

@pydolan Sim, verifique http://stackoverflow.com/questions/21787938/inherit-and-modify-a-meta-class para algumas outras abordagens também.

Esta página foi útil?
0 / 5 - 0 avaliações