Django "list_filter" на основе набора запросов администратора - PullRequest
1 голос
/ 08 апреля 2019

Я занимаюсь разработкой приложения, в котором есть как администраторы, так и суб-администраторы.Субадминистраторы создаются на основе группы, к которой они принадлежат.Таким образом, субадмин может видеть только данные, относящиеся к его группе.Эта функция работает отлично.

Теперь я хочу создать опцию фильтра на основе пользователей.Для супер-админа это работает нормально, но когда я вижу из суб-админа, я вижу полный список пользователей в списке фильтров.Как я могу ограничить этот список в зависимости от количества пользователей с правами администратора?

Предположим, что в общей сложности 20 пользователей, а у подчиненного администратора только 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:

Произведены следующие модификации, но фильтр не виден.

# 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()

ЗАКЛЮЧИТЕЛЬНОЕ РАБОЧЕЕ РЕШЕНИЕ (СПАСИБО @dirkgroten):

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

Ответы [ 2 ]

1 голос
/ 08 апреля 2019

Не меняйте 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
1 голос
/ 08 апреля 2019

Если я правильно понял ваш вопрос, вы должны переопределить метод get_list_filter() вместо get_queryset(),

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

    list_filter = ('user',)

    <b>def get_list_filter(self, request):
        if request.user in [your_three_user_list]:
            return self.list_filter
        else:
            return ()</b>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...