Given a User can belong to more than one Group, I would like to ask how to filter on Groups in the below scenario.
In Django I have a ListView showing a product list .
I have 5 users: Worker_1, Worker_2, Worker_3, Worker_4, Inspector
Worker_1, Worker_2, belongs to "Company_1"
Inspector has no superuser status or staff status, It should be seen as a normal user that belongs to two groups ['Company_1', 'Company_2']
Desired functionality:
Worker_1 register their own manufactured products in the application and can see a list of all products manufactured by Company_1.
Inspector can see all products, from Company_1 and Company_2
In the below code attempts, however, Inspector cannot see any products.
As Inspector belongs to ['Company_1', 'Company_2'] I need a way to check each Group membership in the list against the Group registered for a product. Please note that below are simplified into two groups but in reality x number of groups and users.
in 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)
within views.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)))
Since your definition of the inspector is clear, we can then add some conditions in the get_queryset function. Here is a pseudo-code:
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)))
I hope this helps, let me know if it's not working :)
I came up with a really ugly solution, but have to work for now. Ideally, I need to figure out a dynamic way to express this. The real problem was to dynamically construct filters and combine those, especially with the manual construct of " | ". There might exist a better solution, but for now I couldn't find it, or figure it out.
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
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.