【问题标题】:"list_editable" doesn't work in admin changelist view, using custom get_queryset() method“list_editable”在管理更改列表视图中不起作用,使用自定义 get_queryset() 方法
【发布时间】:2017-06-15 15:48:00
【问题描述】:

我在整个项目中使用自定义抽象模型和经理。

class BaseQueryset(models.QuerySet):

   pass


class BaseManager(models.Manager):
   queryset_class = BaseQueryset

    def get_queryset(self, exclude_no_published=True):
        """ exclude all objects with is_published=False by default """
        q = self.queryset_class(self.model)
        if exclude_no_published:
            q = q.exclude(is_published=False)
        return q

    def all_objects(self):
        """ allows geting all objects in admin """
        return self.get_queryset(exclude_no_published=False)


class BaseAbstractModel(models.Model):

    is_published = models.BooleanField(default=True)

    objects = BaseManager()

    class Meta:
        abstract = True

所有模型都继承自这个抽象模型,我需要一种方法来表示 admin 中的所有对象。所以我用get_queryset 方法为管理类编写了自己的mixin

class AdminFullQuerysetMixin(object):

    def get_queryset(self, request):
    """
    Allows showing all objects despite on is_public=False
    """
        qs = self.model.objects.all_objects()
        ordering = self.get_ordering(request)
        if ordering:
            qs = qs.order_by(*ordering)
        return qs

这是我典型的管理类:

@admin.register(SomeModel)
class SomeModelAdmin(AdminFullQuerysetMixin, admin.ModelAdmin):

    list_display = ('name', 'slug', 'is_published')
    list_filter = ('is_published',)
    list_editable = ('is_published',)

一切正常,无论is_published False 还是True,我都可以在admin 中看到所有对象。但是当我在管理对象列表页面中使用它时,像list_filterlist_editable 这样的属性不起作用。没有提供任何例外,只是列表顶部的文字:“请更正以下错误”。
除了get_queryset,我应该重写哪些方法来解决我的问题?

【问题讨论】:

  • 请为您的管理类添加代码
  • @ResleyRodrigues 问题已更新,但管理员中没有这样的逻辑。我的 mixin 中 get_queryset 的所有问题,没有那个 mixin 都可以正常工作,但我看不到 is_published=False 的对象,因为 Django 使用我的自定义查询集
  • 我不确定出了什么问题,但另一种方法是在您的经理 (.published()) 中使用自定义查询集并在需要时使用它,让管理员使用 .all()。这样你就不需要 AdminFullQuerysetMixin 也不需要 all_objects()
  • @ResleyRodrigues 你是对的,但在这种情况下,我需要在任何地方调用 published(),而不是在管理员中的一个地方,因为默认情况下我不需要带有 is_published=False 的项目

标签: django django-admin


【解决方案1】:

你可能想read this

如果您使用自定义 Manager 对象,请注意第一个 Manager Django 遇到(按照它们在模型中定义的顺序) 有着特殊的地位。 Django 解释第一个 Manager 中定义的 类作为“默认”管理器,Django (...) 的几个部分将 将该 Manager 专门用于该模型。结果,这是一个 在选择默认管理器时要小心谨慎,以便 避免覆盖 get_queryset() 导致 无法检索您想要使用的对象

我强烈怀疑你遇到了其中一个案例……

然后解决方案是将您的模型更改为:

class BaseAbstractModel(models.Model):

    is_published = models.BooleanField(default=True)

    # this one will be the default manager
    all_objects = models.Manager()

    # and this one will be known as 'objects' 
    objects = BaseManager()

    class Meta:
        abstract = True

然后您可以删除您的 AdminFullQuerysetMixin(或重写它的 get_queryset() 方法以使用 self.model._default_manager 代替)

注意:我当然可能是错的,问题完全不相关;)

【讨论】:

  • 感谢您的回答,但我的经理按我的预期工作。带有is_published=False 的对象不应在项目的任何部分(管理员除外)中查看,例如,我不想在我的 DRF 序列化程序中显示带有False 标志的对象,但我需要有机会在管理员中更改它们的状态。我认为这种方法比编写两个单独的管理器更干。我希望我能在changelist_view 方法中找到解决方案,我认为问题就在这里。
  • 您的经理可能会像您期望的那样工作,但它显然不能像 Django 期望的(部分)那样工作 - 我看不出使用两个经理如何让您的代码比使用您的方法更干燥.但是,好吧,你的电话;)
  • 我认为用 False 标记它类似于删除实例,但总是可以在管理员中将其返回。在这种情况下,我只需要在管理员中调用all_objects,在项目的其他部分中,所有实例都将被隐藏。你的方法很棒,我明天试试。取决于你在 Django 中的经验,确定你知道如何构建它比我更好,我只是担心当我不需要时,Django 会在我的项目的其他部分调用默认的all_objects manager。
  • 我在我的项目中实现了您的解决方案。确实很简单明了,谢谢楼主
猜你喜欢
  • 2013-05-04
  • 2016-01-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-17
  • 2017-03-19
相关资源
最近更新 更多