AlASAD WAIL
AlASAD WAIL

Reputation: 825

Filter queryset accouring to related objects in django

I used django-guardian library, I want to create Manager to filter objects according to user permission.

So for-example:

 from guardian.shortcuts import get_objects_for_user
 class WithUser(models.Manager):
     user_obj = None
     def assign_user(self,user_obj):
         self.user_obj = user_obj
         qs = super().get_queryset()
         #########################
         # how I know if the current qs have related field and how to get related field managers.
         #???????????????
     def get_queryset(self):
         qs = super().get_queryset()
         if self.user_obj:
              qs = get_objects_for_user(self.user_obj,"view_%s"%self.model.__name__.lower(),qs,accept_global_perms=False)
         return qs

class A(models.Model):
    # the model fields
    objects = WithUser()

class B(models.Model):
    # the model fields
    a = models.ForeignKey(A,on_delete=Model.CASCADE)
    objects = WithUser()

class C(models.Model):
    # the model fields
    b = models.ForeignKey(B,on_delete=Model.CASCADE)
    objects = WithUser()

How to filter C objects according to it's permission and permission of A,B.

I want general rule to filter any model objects according to its permission and permission of its related objects.

Upvotes: 1

Views: 129

Answers (1)

rabbit.aaron
rabbit.aaron

Reputation: 2589

I would create a special ForeinKey field to mark the fields.

class PermissionForeignKey(models.ForeignKey):
    # we only use this class to mark the field
    pass

# you can add lru_cache here to speed up
# you could also move this to the model as @classproperty
def perm_fk_fields(model):
    fk_fields = []
    for field in model._meta.get_fields():
        if isinstance(field, PermissionForeignKey):
            fk_fields.append(field)
            fk_model_fields = perm_fk_fields(field.remote_field.model)
            if fk_model_fields:
                fk_fields.append([field, fk_model_fields])

    return fk_fields

# in your model
class B(models.Model):
    # the model fields
    a = PermissionForeignKey(A,on_delete=Model.CASCADE)

Upvotes: 1

Related Questions