Python “Django”;列表“U过滤器”;基于管理查询集

Python “Django”;列表“U过滤器”;基于管理查询集,python,django,Python,Django,我正在开发一个既有管理员又有副管理员的应用程序。子管理员是根据其所属的组创建的。因此,副管理员只能查看与其组相关的数据。此功能工作正常 现在,我想创建一个基于用户的过滤器选项。对于超级管理员,它可以正常工作,但是当我从sub-admin查看时,我可以在过滤器列表中看到完整的用户列表。如何根据子管理员用户限制此列表 假设总共有20个用户,而sub admin在他的组中只有3个用户。因此,我只能在列表视图中看到3个,但在过滤器选项中,我可以看到所有20个。我可以将此筛选器仅限于这3个用户吗 我的管理

我正在开发一个既有管理员又有副管理员的应用程序。子管理员是根据其所属的组创建的。因此,副管理员只能查看与其组相关的数据。此功能工作正常

现在,我想创建一个基于用户的过滤器选项。对于超级管理员,它可以正常工作,但是当我从sub-admin查看时,我可以在过滤器列表中看到完整的用户列表。如何根据子管理员用户限制此列表

假设总共有20个用户,而sub admin在他的组中只有3个用户。因此,我只能在列表视图中看到3个,但在过滤器选项中,我可以看到所有20个。我可以将此筛选器仅限于这3个用户吗

我的管理模型如下所示:

class VideoDetailsAdmin(admin.ModelAdmin):
    list_display = ('video_id', 'user', 'status', 'description', 'video_name', 'upload_time', 'duration')

    list_filter = ('user', )

    def get_queryset(self, request):
        # Get the groups of logged in user
        query_set = Group.objects.filter(user = request.user)
        group_list = []
        for g in query_set:
            group_list.append(g.name)
        # Get the user ids of Users in those groups
        id_list = []
        for user in list(User.objects.filter(groups__name__in=group_list)):
            id_list.append(user.id)
        # Create unique users list
        users = list(set(id_list))
        # Override the get_queryset method for Admin
        qs = super(VideoDetailsAdmin, self).get_queryset(request)

        if not request.user.is_superuser:
            return qs.filter(user__in = users)
        else:
            return qs
我在Django上看到的资源很少,但我想知道解决这个问题的最佳方法是什么。有没有办法重复使用get_queryset()代码

Django版本:2.1

编辑1:

class UserFilterList(SimpleListFilter):
    title = "user"
    parameter_name = "user"
    def lookups(self, request, model_admin):
        visible_users = model_admin.get_visible_users(request)
        print(visible_users[0])
        return ((user, user) for user in visible_users)

    def queryset(self, request, queryset):
        return self.value()
class UserFilterList(SimpleListFilter):
    title = "user"
    parameter_name = "user"
    def lookups(self, request, model_admin):
        if not request.user.is_superuser:
            visible_users = model_admin.get_visible_users(request)
            # Sub user - return same group users
            return ((user.id, user) for user in visible_users)
        else:
            # Superuser - return all users
            return ((user.id, user) for user in User.objects.filter())

    def queryset(self, request, queryset):
        return queryset.filter(user=self.value()) if self.value() else queryset

class VideoDetailsAdmin(admin.ModelAdmin):
    list_display = ('video_id', 'user', 'status', 'description', 'video_name', 'upload_time', 'duration')

    list_filter = (UserFilterList, )

    def get_visible_users(self, request):
        # Get the groups of logged in user
        query_set = Group.objects.filter(user = request.user)
        group_list = []
        for g in query_set:
            group_list.append(g.name)
        return User.objects.filter(groups__name__in=group_list)

    def get_queryset(self, request):
        users = self.get_visible_users(request)

        # Override the get_queryset method for Admin
        qs = super(VideoDetailsAdmin, self).get_queryset(request)

        if not request.user.is_superuser:
            return qs.filter(user__in = users)
        else:
            return qs
进行了以下修改,但没有可见的过滤器

# Filter list
class UserFilterList(admin.SimpleListFilter):
    # Human readable title, which is displayed on the right sidebar
    title = ("User")

    # Parameter for the filter that will be used in the URL query
    parameter_name = "user"

    def lookups(self, request, model_admin):
        # To get user's groups
        query_set = Group.objects.filter(user = request.user)
        group_list = []
        for g in query_set:
            group_list.append(g.name)
        # To get all users associated in those groups
        id_list = []
        for user in list(User.objects.filter(groups__name__in=group_list)):
            id_list.append(user.id)

        users = list(set(id_list))
        qs = model_admin.get_queryset(request)

    def queryset(self, request, queryset):
        if not request.user.is_superuser:
            return qs.filter(user__in = users)
        else:
            return qs
编辑2:

class UserFilterList(SimpleListFilter):
    title = "user"
    parameter_name = "user"
    def lookups(self, request, model_admin):
        visible_users = model_admin.get_visible_users(request)
        print(visible_users[0])
        return ((user, user) for user in visible_users)

    def queryset(self, request, queryset):
        return self.value()
class UserFilterList(SimpleListFilter):
    title = "user"
    parameter_name = "user"
    def lookups(self, request, model_admin):
        if not request.user.is_superuser:
            visible_users = model_admin.get_visible_users(request)
            # Sub user - return same group users
            return ((user.id, user) for user in visible_users)
        else:
            # Superuser - return all users
            return ((user.id, user) for user in User.objects.filter())

    def queryset(self, request, queryset):
        return queryset.filter(user=self.value()) if self.value() else queryset

class VideoDetailsAdmin(admin.ModelAdmin):
    list_display = ('video_id', 'user', 'status', 'description', 'video_name', 'upload_time', 'duration')

    list_filter = (UserFilterList, )

    def get_visible_users(self, request):
        # Get the groups of logged in user
        query_set = Group.objects.filter(user = request.user)
        group_list = []
        for g in query_set:
            group_list.append(g.name)
        return User.objects.filter(groups__name__in=group_list)

    def get_queryset(self, request):
        users = self.get_visible_users(request)

        # Override the get_queryset method for Admin
        qs = super(VideoDetailsAdmin, self).get_queryset(request)

        if not request.user.is_superuser:
            return qs.filter(user__in = users)
        else:
            return qs
最终工作解决方案(感谢@dirkgroten):

class UserFilterList(SimpleListFilter):
    title = "user"
    parameter_name = "user"
    def lookups(self, request, model_admin):
        visible_users = model_admin.get_visible_users(request)
        print(visible_users[0])
        return ((user, user) for user in visible_users)

    def queryset(self, request, queryset):
        return self.value()
class UserFilterList(SimpleListFilter):
    title = "user"
    parameter_name = "user"
    def lookups(self, request, model_admin):
        if not request.user.is_superuser:
            visible_users = model_admin.get_visible_users(request)
            # Sub user - return same group users
            return ((user.id, user) for user in visible_users)
        else:
            # Superuser - return all users
            return ((user.id, user) for user in User.objects.filter())

    def queryset(self, request, queryset):
        return queryset.filter(user=self.value()) if self.value() else queryset

class VideoDetailsAdmin(admin.ModelAdmin):
    list_display = ('video_id', 'user', 'status', 'description', 'video_name', 'upload_time', 'duration')

    list_filter = (UserFilterList, )

    def get_visible_users(self, request):
        # Get the groups of logged in user
        query_set = Group.objects.filter(user = request.user)
        group_list = []
        for g in query_set:
            group_list.append(g.name)
        return User.objects.filter(groups__name__in=group_list)

    def get_queryset(self, request):
        users = self.get_visible_users(request)

        # Override the get_queryset method for Admin
        qs = super(VideoDetailsAdmin, self).get_queryset(request)

        if not request.user.is_superuser:
            return qs.filter(user__in = users)
        else:
            return qs

不要更改您的
VideoDetailsAdmin
,只使用自定义列表筛选器:

class VideoDetailsAdmin(ModelAdmin):
    list_filter = UserFilterList  # that's the only line to change

    def get_visible_users(self, request):  # small refactor to re-use in filter
        query_set = Group.objects.filter(user=request.user)
        group_list = []
        for g in query_set:
            group_list.append(g.name)
        # To get all users associated in those groups
        return User.objects.filter(groups__name__in=group_list)

    def get_queryset(self, request):
        users = self.get_visible_users(request)
        # Override the get_queryset method for Admin
        qs = super(VideoDetailsAdmin, self).get_queryset(request)

        if not request.user.is_superuser:
            return qs.filter(user__in=users)
        else:
            return qs

class UserFilterList(SimpleListFilter):
    def lookups(self, request, model_admin):
        visible_users = model_admin.get_visible_users(request)
        return ((user.pk, user.username) for user in visible_users)

    def queryset(self, request, queryset):
        return queryset.filter(user_id=self.value()) if self.value() else queryset

如链接到的文档所示,您需要通过子类化
SimpleListFilter
来创建自己的列表过滤器。这两种方法都是非常自我解释的,只是根据用户是管理员还是副管理员,将不同的列表返回到
lookups
。尤其是更下面的绿色音符应该会有帮助。所以你应该先试试,如果你被卡住了,请寻求帮助。你打算如何区分这三个用户?基于普通组。我已经在上面提到的代码中实现了这一点piece@dirkgroten下面是我对代码的理解-它将基于定制的过滤器获得结果,在这种情况下是80年代,90年代等等,但我实际上在寻找的是限制边栏本身的元素,django应该使用它的逻辑来检索结果。假设管理员在侧边栏中有20个用户,我希望sub-Admin只看到3个用户。这3个用户将根据用户与此子管理员的组相似性来确定。否,
lookups()
将返回列表筛选器中显示的选项。因此,您应该返回要显示的3个用户。它们是元组(值,显示),在您的例子中是(
id
name
)。然后,
queryset()
是基于所选值返回的查询,但在您的情况下,它只是默认值,因此您可能不需要覆盖它。我需要做一些修改,例如添加def queryset(),否则它是不允许的。虽然我正在寻找用户名,但现在我可以看到用户id,但当我点击它时,什么都没有发生。请选中EDIT 2 Now it链接正在工作,但默认情况下,它不显示任何内容,如果我单击“全部”,它将不显示任何内容。虽然当我单击单个用户ID时它工作正常,但是我在元组中输入的值可能是错误的方式,或者发布了错误的类型。检查浏览器源代码以查看链接中的值,并在
def queryset()
内设置断点以检查
self.value()
是什么。是的,self.value()为空表示“全部”。默认self.value()为无,但当我选择单个元素时,它是那些元素(如44、26等)的值。