Визуализация django_tables2.Column с выбранным тегом внутри (ОБНОВЛЕНО) - PullRequest
0 голосов
/ 15 февраля 2019

Я написал настраиваемую редактируемую таблицу с подклассами столбцов от 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 *

1 Ответ

0 голосов
/ 15 февраля 2019

Итак, как я случайно обнаружил, проблема была в атрибуте accessor - при изменении с

used_as = ChoiceColumn(UsedAs.choices(), accessor='used_as')

на

used_as = ChoiceColumn(UsedAs.choices(), accessor='pk')

он, наконец, отображался.Я не понимаю, почему это произошло, и был бы очень признателен, если бы кто-то объяснил мне это.

...