django-tables2 игнорирует ManyToManyField

У меня есть эти модели:

class Category(models.Model):
    name = models.CharField(max_length=10)
    uuid = models.CharField(max_length=36)

class Item(models.Model):
    name = models.CharField(max_length=255)
    uuid = models.CharField(max_length=36)
    categories = models.ManyToManyField(Category, null=True)
    brand = models.ForeignKey(Brand)

Я пытаюсь отобразить модель Item в таблице с помощью django-tables2, например:

class ItemTable(tables.Table):
    class Meta:
        model = Item
        attrs = {"class": "paleblue"}
        fields = ("uuid", "name", "brand", "categories")

    categories = tables.Column(empty_values=())

    def render_categories(self, value):
        return ', '.join([category.name for category in value.all()])

Он работает нормально, за исключением того, что Table игнорирует поле categories, а параметр value равен None, и я получаю сообщение об ошибке 'NoneType' object has no attribute 'all'

Что я делаю не так? Спасибо.


person Wayfaerer    schedule 03.10.2014    source источник


Ответы (5)


Сделай это:

class ItemTable(tables.Table):
    class Meta:
        model = Item
        attrs = {"class": "paleblue"}
        fields = ("uuid", "name", "brand", "categories")

    categories = tables.Column()

    def render_categories(self, value):
        if value is not None:
            return ', '.join([category.name for category in value.all()])
        return '-'
person ruddra    schedule 03.10.2014
comment
Я обнаружил, что value = None является следствием ошибки в django-tables2 (посмотрите мой ответ выше), он игнорирует ManyToManyField в модели. Так что, если я буду делать то, что вы написали, я всегда буду получать '-' в результате. Решение состоит в том, чтобы исправить ошибку в django-tables2 - person Wayfaerer; 04.10.2014

Похоже, это ошибка в django-tables2 при использовании с django 1.7: https://github.com/bradleyayers/django-tables2/issues/211

person Wayfaerer    schedule 03.10.2014

Похоже, что он не был объединен. В качестве обходного пути вы можете выполнить рендеринг с записью и выполнить итерацию таким же образом.

ie.

 def render_categories(self, record):
        if record.category is not None:
            return ', '.join([category.name for category in record.category.all()])
        return '-'
person Craig    schedule 23.04.2015
comment
Упс. Вам понадобится новое поле для использования, потому что похоже, что django-tables2 возвращает значение на основе поля. Так что просто создайте новую колонку или что-то в этом роде, чтобы получить полную запись. - person Craig; 24.04.2015
comment
Привет @Craig, добро пожаловать в StackOverflow. Вы можете отредактировать свой вопрос, чтобы скрыть свой позор. Если прошло пять минут, это будет зарегистрировано как редактирование, но лучше отредактировать, чем опубликовать исправление в виде комментария. :) - person Wai Ha Lee; 24.04.2015

Возможно, это не более чистый вариант, но это сработало для меня:

class Item(models.Model):
    name = models.CharField(max_length=255)
    uuid = models.CharField(max_length=36)
    categories = models.ManyToManyField(Category, null=True)
    brand = models.ForeignKey(Brand)

   @property
   def categories_str(self):
       return ', '.join([category.name for category in value.all()])


class ItemTable(tables.Table):
    categories = tables.Column(accessor='categories_str')

    class Meta:
        model = Item
        attrs = {"class": "paleblue"}
        fields = ("uuid", "name", "brand", "categories")
person Marc Tudurí    schedule 13.05.2015

Сделай это:

class ItemTable(tables.Table):
    class Meta:
        model = Item
        attrs = {"class": "paleblue"}
        fields = ("uuid", "name", "brand", "categories")

    categories = tables.Column(empty_values=())

    def render_categories(self, record):
        if record.categories.all():
            return ', '.join([category.name for category in record.categories.all()])
        return '-'

Обратите внимание, что empty_values=() важно записать в таблицы. Column()

person Paritosh Gupta    schedule 28.08.2015