Я написал настраиваемую редактируемую таблицу с подклассами столбцов от django_tables2.Column
, но продолжаю бороться с отображением тега select в моем настраиваемом столбце.Учитывая модель:
myapp / models.py
from django.db import models
from myapp.utils.enums import MyModelChoices
class MyModel(models.Model):
bound_model = models.ForeignKey(
SomeOtherModel,
related_name='bound_model'
)
used_as = models.CharField(
max_length=50,
blank=True,
null=True,
choices=MyModelChoices.choices()
)
и мой enum в myapp / utils / enums.py :
class MyModelChoices:
__metaclass__ = EnumMeta # Logic irrelevant
First = 'First',
Second = 'Second',
Third = 'Third'
Я получаю пользовательский столбец, подобный этому:
import django_tables2 as tables
from django.forms import ChoiceField
class ChoicesColumn(tables.Column):
def __init__(self, choices, attrs=None, **extra):
self.choices = choices
kwargs = {'orderable': False, 'attrs': attrs}
kwargs.update(extra)
super(ChoicesColumn, self).__init__(**kwargs)
def render(self, value, bound_column):
select = ChoiceField(choices=self.choices)
return select.widget.render(
bound_column.name,
self.label_to_value(value)
)
def label_to_value(self, label):
for (v, l) in self.choices:
if l == label:
return v
, который позже вызывается в моем табличном классе, как этот:
import django_tables2 as tables
from myapp.models import MyModel
from myapp.tables.utils import ChoicesColumn
class MyTable(tables.Table):
name = tables.Column()
used_as = ChoicesColumn(
choices=lambda record: record.used_as.choices()
)
def render_name(self, record):
return record.bound_model.name
class Meta:
model = MyModel
fields = ('name', 'used_as',)
, но все равно он отображается толькообычный <td></td>
с текстом вместо поля выбора.Что я делаю не так в этой ситуации?Я использую Python 2.7, Django 1.8 и django-tables2 1.16.0.Заранее спасибо за совет!
ОБНОВЛЕНИЕ
Я изменил свой класс пользовательских столбцов следующим образом:
class ChoicesColumn(tables.Column):
def __init__(self, attrs=None, **extra):
kwargs = {'orderable': False, 'attrs': attrs}
kwargs.update(extra)
super(ChoicesColumn, self).__init__(**kwargs)
def render(self, value, bound_column):
options = [self.render_option(c) for c in value]
html_template = '''
<select name={}>{}</select>
'''.format(bound_column.name, options)
return mark_safe(html_template)
def render_option(self, choice):
return '<option value={0}>{0}</option>'.format(choice)
и добавил render_options
метод в соответствии с этим параграфом в документации:
class MyTable(tables.Table):
name = tables.Column(accessor='pk')
# With or without accessor it doesn't work neither way
used_as = ChoicesColumn(accessor='used_as')
def render_name(self, record):
return record.bound_model.name
def render_used_as(self, record):
return record.used_as.choices()
class Meta:
model = MyModel,
fields = ('name', 'options',)
, но этот метод даже не выполняется при рендеринге, что я заметил при отладке, хотя метод перед его выполнением, когда яперезагрузить страницу и правильно отображает данные.Это потому, что столбец name
использует класс библиотеки, а столбец options
использует пользовательский класс, унаследованный от него?Если так, то чего не хватает моему подклассу?
ДРУГОЕ ОБНОВЛЕНИЕ
Я выяснил, что было предыдущей проблемой с выбором, хотя это не решило проблему :(Дело в том, что я передавал поле экземпляра модели used_as
, которое было установлено на None
, поэтому оно никогда не заполняло ChoiceField, поэтому я откатил свой класс пользовательских столбцов к исходному варианту и вместо этого в своем классе таблицыиз
used_as = ChoicesColumn(
choices=lambda record: record.used_as.choices()
)
Я импортировал MyModelChoices
enum и использовал его вместо экземпляра модели
used_as = ChoicesColumn(choices=MyModelChoices.choices())
, и теперь я вижу опции, передаваемые конструктору, хотя метод render
isn 't по-прежнему вызывается по какой-то таинственной причине = /
ПОСЛЕДНИЕ ОБНОВЛЕНИЯ КАК СЕЙЧАС Что касается текущего момента, мои пользовательские столбец и таблица выглядят так:
class ChoicesColumn(tables.Column):
def __init__(self, choices, attrs=None, **extra)
self.choices = choices
self.choices.insert(0, ('', '------'))
kwargs = {'orderable': False, 'attrs': attrs}
kwargs.update(extra)
super(ChoicesColumn, self).__init__(**kwargs)
def render(self, value, bound_column):
select = forms.ChoiceField(choices=self.choices)
return select.widget.render(bound_column.name, value)
class MyTable(tables.Table):
name = tables.Column(accessor='pk')
used_as = ChoiceColumn(UsedAs.choices(), accessor='used_as')
def render_name(self, record):
return record.bound_model.name
def render_used_as(self, record):
if record.used_as is None:
return ''
return record.used_as
class Meta:
model = MyModel
fields = ('name', 'used_as')
ChoiceColumn
метод рендеринга и соответствующий метод в классе таблицы никогда не вызываются на этапе рендеринга (в отличие от других столбцов), и я полностью сдаюсь. Пожалуйста, будьте милостивыми, чтобы застрелить меня или сказать, где точнотли я идиот :) 1062 *