Files
2023-10-16 17:24:17 +02:00

75 lines
3.0 KiB
Python

from django.contrib import admin
from django.contrib.admin import ModelAdmin, StackedInline
from tenants.access import can_pick_tenant, filter_for_user, get_tenant_accessor
from tenants.forms import TenantModelForm
class GetQuerySetMixin:
def get_queryset(self, request):
qs = super().get_queryset(request)
if can_pick_tenant(request.user):
return qs
return filter_for_user(self.model, request.user)
class TenantModelAdmin(GetQuerySetMixin, ModelAdmin):
form = TenantModelForm
def get_form(self, request, obj=None, change=False, **kwargs):
form = super().get_form(request, obj, change, **kwargs)
form.user = request.user
return form
def formfield_for_foreignkey(self, db_field, request, **kwargs):
if not can_pick_tenant(request.user):
tenant_model = db_field.related_model
kwargs['queryset'] = filter_for_user(tenant_model, request.user)
return super().formfield_for_foreignkey(db_field, request, **kwargs)
def get_exclude(self, request, obj=None):
result = super().get_exclude(request, obj)
if not can_pick_tenant(request.user):
result = list(result or []) + ['tenant']
return result
def get_list_display(self, request):
result = list(super().get_list_display(request))
if can_pick_tenant(request.user):
tenant_accessor = get_tenant_accessor(self.model)
# Django doesn't support transitive relations in list_display:
if '__' not in tenant_accessor:
field = self.model._meta.get_field('tenant')
if field.many_to_many:
@admin.display(description='tenant')
def get_tenant(obj):
accessor_name = field.get_accessor_name()
return ', '.join(
str(t) for t in getattr(obj, accessor_name).all()
)
result = [get_tenant] + result
else:
result = [tenant_accessor] + result
return result
def get_list_display_links(self, request, list_display):
return self.get_list_display(request)
def get_list_filter(self, request):
result = list(super().get_list_filter(request))
if can_pick_tenant(request.user):
result = [get_tenant_accessor(self.model)] + result
return result
def lookup_allowed(self, lookup, value):
# Allow filtering by tenant for models whose tenant field is transitive.
# For example: Version -> Package -> Tenant. As a superuser, we want to
# be able to filter versions by tenant. Without the following code, we
# would get a `DisallowedModelAdminLookup` when trying to do this.
tenant_accessor = get_tenant_accessor(self.model)
if lookup == tenant_accessor + '__id__exact':
return True
return super().lookup_allowed(lookup, value)
class TenantStackedInline(GetQuerySetMixin, StackedInline):
pass