【问题标题】:Django MPTT tree as model filter in adminDjango MPTT 树作为管理员中的模型过滤器
【发布时间】:2019-07-28 15:14:59
【问题描述】:

我有一个模型链接到一个相关模型,它是一个 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: 我认为我已将问题隔离为以下事实,即我在 Tenders to Sectors 中的外键使用 to_field='sectorId 而不是默认链接到 pk 列。必须这样做是为了向后兼容我坚持使用的旧数据库方案。

【问题讨论】:

    标签: django django-models django-admin django-mptt django-admin-filters


    【解决方案1】:

    所以事实证明这是TreeRelatedFieldListFilter 类中field_choices 函数的django-mptt 代码中的一个错误。

    要修复它,我必须继承并覆盖该函数以使用我定义的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
    

    【讨论】:

      猜你喜欢
      • 2010-10-11
      • 2021-01-01
      • 2012-09-04
      • 1970-01-01
      • 2011-05-11
      • 2011-11-13
      • 2011-03-05
      • 2011-01-23
      • 2011-03-04
      相关资源
      最近更新 更多