Django: фильтрация списка в группах / итерация набора запросов по списку - PullRequest
0 голосов
/ 06 марта 2020

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

В Django У меня есть ListView, отображающий список продуктов .

  • У меня есть две группы: Компания_1, Компания_2.
  • У меня 5 пользователей: Работник_1, Работник_2, Работник_3, Работник_4, Инспектор

  • Работник_1, Работник_2, принадлежит «Компании_1»

  • Работник_3, Работник_4, принадлежит «Компании_2»
  • «Инспектор» может проверять всю продукцию обеих компаний

Инспектор не имеет статуса суперпользователя или штата. Его следует рассматривать как обычного пользователя, который принадлежит к двум группам ['Company_1', 'Company_2']

Желаемый функциональность:

Работник_1 регистрирует свои собственные изготовленные продукты в приложении и может видеть список всех продуктов, произведенных Company_1.

Инспектор может видеть все продукты, от Company_1 и Company_2

В приведенных ниже попытках кода однако Инспектор не может видеть никаких продуктов.

Поскольку Инспектор принадлежит ['Company_1', 'Company_2'], мне нужен способ, чтобы проверить каждое членство Группы в списке по отношению к Группе, зарегистрированной для продукта. Обратите внимание, что ниже упрощены на две группы, но на самом деле х количество групп и пользователей.

в models.py

from django.contrib.auth.models import User

class Product(models.Model):
    worker = models.ForeignKey(User, blank=True, on_delete=models.CASCADE)
    company = models.CharField(max_length=100, null=True, blank=True)

    def save(self, *args, **kwargs):
        self.company = list(self.worker.groups.all().values_list('name', flat=True))
        super(Product, self).save(*args, **kwargs)

в представлениях. py

class ProductListView(LoginRequiredMixin, ListView):
    model = Product
    template_name = 'product_list.html'

    def get_queryset(self):
        queryset = super(ProductListView, self).get_queryset()
        return queryset.filter(company__contains=list(self.request.user.groups.all().values_list('name', flat=True)))

Ответы [ 2 ]

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

Я придумала действительно уродливое решение, но сейчас надо работать. В идеале мне нужно найти динамический c способ express этого. Реальная проблема состояла в том, чтобы динамически создавать фильтры и комбинировать их, особенно с ручной конструкцией "|". Возможно, существует лучшее решение, но пока я не смог его найти или выяснить.

class ProductListView(LoginRequiredMixin, ListView):
    model = Product
    template_name = 'product_list.html'

    def get_queryset(self):
        queryset = super(ProductListView, self).get_queryset()

        f = []
        for g in self.request.user.groups.all():
            f.append(f'{g}')

        d = len(f)

        if d == 0:
            g = queryset.filter(company__contains=f"")
        elif d == 1:
            g = queryset.filter(company__contains=f[0])
        elif d == 2:
            g = queryset.filter(company__contains=f[0]) | queryset.filter(company__contains=f[1])
        elif d == 3:
            g = queryset.filter(company__contains=f[0]) | queryset.filter(company__contains=f[1]) \
                | queryset.filter(company__contains=f[2])
        elif d == 4:
            g = queryset.filter(company__contains=f[0]) | queryset.filter(company__contains=f[1]) \
                | queryset.filter(company__contains=f[2]) | queryset.filter(company__contains=f[3])
        elif d == 5:
            g = queryset.filter(company__contains=f[0]) | queryset.filter(company__contains=f[1]) \
                | queryset.filter(company__contains=f[2]) | queryset.filter(company__contains=f[3]) \
                | queryset.filter(company__contains=f[4])
        elif d == 6:
            g = queryset.filter(company__contains=f[0]) | queryset.filter(company__contains=f[1]) \
                | queryset.filter(company__contains=f[2]) | queryset.filter(company__contains=f[3]) \
                | queryset.filter(company__contains=f[4]) | queryset.filter(company__contains=f[5])
        else:
            g = queryset

        return g
0 голосов
/ 06 марта 2020

Поскольку ваше определение инспектора ясно, мы можем добавить некоторые условия в функцию get_queryset. Вот псевдокод:

from django.contrib.auth.models import User, Group

class ProductListView(LoginRequiredMixin, ListView):
    model = Product
    template_name = 'product_list.html'

    def get_queryset(self):
        Company1 = Group.objects.get(name='Company1')
        Company2 = Group.objects.get(name='Company2')
        inspectors = User.objects.filter(groups=Company1 and groups=Company2).distinct() 
        if self.request.user in inspectors:
            return queryset.filter(company=Company1 or company=Company2).distinct().values_list('name', flat=True)))
        return queryset.filter(company__contains=list(self.request.user.groups.all().values_list('name', flat=True)))

Надеюсь, это поможет, дайте мне знать, если он не работает:)

...