Django запрос к иерархическим моделям (Проектирование диапазонов разрешений)

Я пытаюсь разработать набор диапазонов для разрешений, используя модели Django. Аналогично группам, но с другими целями.

Side Note 1: I'm not sure if django-mptt is a solution to my problem or not. As I have different related models I guess it's not. Side Note 2: I can't use Django's group as I'm using them as roles (basically to group permissions together).

Imagine that I have Paris and Berlin as my Cities, Art_school with Paris as the parent and Engineering_school with Berlin as its parent. Each school can have any number of classes. And using generic foreign key on User model, each user can be in one of these entities.

  • What's the purpose of this design? (I'm trying to create some scope for permissions).
    • Anyone in a city with add_user permission can add users to that city, schools and all classes under that city.
    • Anyone in a school with add_user permission can add users to that school and all classes under that school.
    • Anyone in a class with add_user permission can only add users to that class.
    • Same goes for other kind of permissions: add_school, add_class, remove_whatever, etc.

  • What I'm looking for:
    • Using an entity (A city for example) I want to find all its descendant entities.
    • Using an entity I want to find all users on that entity and its descendant entities.

Как правильно это сделать? Сейчас мне нужно найти все школы в городе, затем все классы в этих школах и, наконец, всех пользователей, связанных с этими классами, что требует множества запросов! Должен ли я изменить способ построения моих моделей?

class User(AbstractUser):
    ...
    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
    object_id = models.PositiveIntegerField()
    content_object = GenericForeignKey('content_type', 'object_id')


class City(models.Model):
    name = models.CharField(max_length=140)

    class Meta:
        verbose_name_plural = "1. City"

    def __str__(self):
        return self.name


class School(models.Model):
    name = models.CharField(max_length=140)
    city = models.ForeignKey(City, on_delete=models.CASCADE)

    class Meta:
        verbose_name_plural = "2. School"

    def __str__(self):
        return f"{self.name} ({self.city.name})"


class Class(models.Model):
    name = models.CharField(max_length=140)
    school = models.ForeignKey(School, on_delete=models.CASCADE)

    class Meta:
        verbose_name_plural = "3. Class"

    def __str__(self):
        return f"{self.school.name} {{{self.name}}} ({self.school.city.name})"
Вернуться на верх