我的一般问题是:我可以使用存储在 HStoreField (Django 1.8.9)中的数据为现有的表类动态生成列 django-tables2 ?以下是一个例子,说我有一个模型:
from django.contrib.postgres import fields as pgfields
GameSession(models.Model):
user = models.ForeignKey('profile.GamerProfile')
game = models.ForeignKey('games.Game')
last_achievement = models.ForeignKey('games.Achievement')
extra_info = pgfields.HStoreField(null=True, blank=True)
现在,我说有一个表定义为:
GameSessionTable(tables.Table):
class Meta(BaseMetaTable):
model = GameSession
fields = []
orderable=False
id = tables.LinkColumn(accessor='id', verbose_name='Id', viewname='reporting:session_stats', args=[A('id')], attrs={'a':{'target':'_blank'}})
started = DateTimeColumn(accessor='startdata.when_started', verbose_name='Started')
stopped = DateTimeColumn(accessor='stopdata.when_stopped', verbose_name='Stopped')
game_name = tables.LinkColumn(accessor='game.name', verbose_name='Game name', viewname='reporting:game_stats', args=[A('mainjob.id')], attrs={'a':{'target':'_blank'}})
我希望能够为所有GameSession
的 extra_info 列中存储的每个密钥添加列。我试图覆盖GameSessionTable类的 init ()方法,在那里我可以访问查询集,然后创建一组GameSession
个对象的所有键,然后添加它们到self
,然而这似乎不起作用。代码如下:
def __init__(self, data, *args, **kwargs):
super(GameSessionTable, self).__init__(data, *args, **kwargs)
if data:
extra_cols=[]
# just to be sure, check that the model has the extra_info HStore field
if data.model._meta.get_field('extra_info'):
extra_cols = list(set([item for q in data if q.extra_info for item in q.extra_info.keys()]))
for col in extra_cols:
self.columns.columns[col] = tables.Column(accessor='extra_info.%s' %col, verbose_name=col.replace("_", " ").title())
请注意,我已经看了https://spapas.github.io/2015/10/05/django-dynamic-tables-similar-models/#introduction,但它没有太多帮助,因为那里的用例与模型的字段有关,而我的情况与你的情况略有不同可以看到上面。
只是想检查,这是否可能,或者我是否必须为此数据定义完全不同的表格,或者可能使用完全不同的库,例如django-reports-builder?
答案 0 :(得分:1)
管理在一定程度上解决这个问题。我上面运行的代码略有错误,因此我更新它以在超类 init()运行之前运行我的代码,并更改我添加列的位置。
结果,我的 init()功能现在看起来像这样:
def __init__(self, data, *args, **kwargs):
if data:
extra_cols=[]
# just to be sure, check that the model has the extra_info HStore field
if data.model._meta.get_field('extra_info'):
extra_cols = list(set([item for q in data if q.extra_info for item in q.extra_info.keys()]))
for col in extra_cols:
self.base_columns[col] = tables.Column(accessor='extra_info.%s' %col, verbose_name=col.replace("_", " ").title())
super(GameSessionTable, self).__init__(data, *args, **kwargs)
请注意,我使用 self.base_columns 替换了 self.columns.columns (这是BoundColumn实例)。这允许超类在初始化Table
类时考虑这些。
可能不是最优雅的解决方案,但它似乎对我有用。