Дерево Django MPTT в качестве фильтра модели в админке - PullRequest
0 голосов
/ 06 марта 2019

У меня есть модель, связанная со связанной моделью, которая представляет собой модель дерева Django MPTT, я хотел бы иметь возможность фильтровать первую модель, используя дерево Django MPTT в консоли администратора.

class Tenders(models.Model):
    ...
    sector=models.ForeignKey(Sector, to_field='sectorId', null=True, blank=True,on_delete=models.CASCADE)
    ...

class Sector(MPTTModel):
    name    = models.CharField(max_length = 255)
    parent  = TreeForeignKey('self', on_delete=models.CASCADE, null=True, blank=True,related_name='children')
    sectorId = models.IntegerField(default=0,null=True,unique=True)

В администраторе Django я хотел бы настроить фильтры для модели Tenders так, чтобы дерево Django-MPTT было фильтром.

Я пытался использовать следующее:

class adminTenders(admin.ModelAdmin):    
   def linkTo(self,obj):
       return mark_safe("""<a href='{}' target="_blank" >Tender Link</a>""".format(obj.tenderLink))
   linkTo.short_description=''

   list_display=(
    'title',
    'linkTo',
    'sector',
    'region',
    'repository',
    'id',
   )
   list_filter=(
    ('sector', TreeRelatedFieldListFilter),
   )

admin.site.register(Tenders,adminTenders)

Однако я получаю следующую ошибку при попытке запустить это, и я не могу понять это:

  File "py36/lib/python3.6/site-packages/mptt/admin.py", line 314, in field_choices
    mptt_level_indent * levels_dict[pk])
  KeyError: 0

Любая помощь будет принята с благодарностью.

Редактировать 1: Я думаю, что изолировал проблему от того факта, что мой внешний ключ в тендерах для секторов использует to_field='sectorId вместо значения по умолчанию для ссылки на столбец pk. Это должно было быть сделано для обратной совместимости со старой схемой базы данных, с которой я застрял.

1 Ответ

0 голосов
/ 07 марта 2019

Получается, что это ошибка в коде django-mptt для функции field_choices в классе TreeRelatedFieldListFilter.

Чтобы исправить это, мне пришлось создать подкласс и перегрузить эту функцию, чтобы использовать to_field, который я определил.

Вот пользовательский код:

class TreeRelatedForSectors(TreeRelatedFieldListFilter):
    # Modified from django-mptt code to fix to_field problem
    def field_choices(self, field, request, model_admin):
        mptt_level_indent = getattr(model_admin, 'mptt_level_indent', self.mptt_level_indent)
        language_bidi = get_language_bidi()
        initial_choices = field.get_choices(include_blank=False)
        pks = [pk for pk, val in initial_choices]
        models = field.related_model._default_manager.filter(sectorId__in=pks)
        levels_dict = {model.sectorId: getattr(model, model._mptt_meta.level_attr) for model in models}
        choices = []
        for pk, val in initial_choices:
            padding_style = ' style="padding-%s:%spx"' % (
                'right' if language_bidi else 'left',
                mptt_level_indent * levels_dict[pk])
            choices.append((pk, val, mark_safe(padding_style)))
        return choices
...