Базовая групповая иерархия в Python Django - PullRequest
0 голосов
/ 03 июля 2019

Я строю систему регистрации студентов, используя django, где студенты регистрируются. Студентов могут видеть только их классные учителя и директора школ на основании разрешения на уровне объекта. Существуют модели School, Class и Student. В каждой школе может быть несколько директоров школ, а в каждом классе может быть более одного учителя класса.

Будет два разрешения на уровне объекта:

  1. Директора школ смогут увидеть всех учеников, зарегистрированных в их школе. Они не смогут видеть учеников других школ.
  2. Учителя классов смогут видеть учеников, которые зарегистрированы в их классах. Они не смогут видеть учеников, зарегистрированных в других классах той же или разных школ.

Я искал различные сторонние библиотеки django для реализации такой иерархической архитектуры групп пользователей. Я видел django-groups-manager , но это немного сложно для моей проблемы. Затем я решил django-mptt регистрация существующих моделей особенность и пришел к реализации модели, такой как:

from django.contrib.auth.models import Group
from django.db import models

import mptt
from mptt.fields import TreeForeignKey

TreeForeignKey(Group, on_delete=models.CASCADE, blank=True,
               null=True).contribute_to_class(Group, 'parent')
mptt.register(Group, order_insertion_by=['name'])


class School(models.Model):
    """School object"""

    name = models.CharField(max_length=255)
    group = models.ForeignKey(
        Group, related_name='school', on_delete=models.CASCADE)


class Class(models.Model):
    """Class object"""

    name = models.CharField(max_length=255)
    group = models.ForeignKey(
        Group, related_name='class', on_delete=models.CASCADE)
    school = models.ForeignKey(
        School,
        on_delete=models.CASCADE
    )


class Student(models.Model):
    """Person object"""

    fullname = models.CharField(max_length=255)
    class = models.ForeignKey(
        Class,
        on_delete=models.CASCADE
    )

Таким образом, каждый объект School и Class будет иметь свои собственные Group s, причем школьная группа является родителем групп классов этой конкретной школы. Теперь я могу создать основных пользователей школы, используя django User и назначить его соответствующей родительской группе. Таким же образом я также могу создавать пользователей-учителей и назначать их дочерним группам своих объектов классов. И когда директор школы или учитель класса хотят просмотреть своих зарегистрированных учеников, я могу применить разрешение на уровне объекта, отфильтровав их группы пользователей.

У меня вопрос, это правильный способ сделать это? Имеет ли смысл создавать одну группу для каждой школы / класса?

1 Ответ

0 голосов
/ 03 июля 2019

Благодаря предложению nigel222 вместо использования встроенных групп django я переопределил встроенную модель django User. Я также следовал этому учебнику, который был действительно полезен. Моя последняя версия models.py выглядит следующим образом (не забудьте переопределить класс User по умолчанию, вам нужно сообщить об этом django, добавив AUTH_USER_MODEL = 'myapp.User' в ваш файл settings.py):

from django.conf import settings
from django.contrib.auth.models import AbstractUser
from django.db import models


class User(AbstractUser):
    """Custom user model with an extra type field"""
    USER_TYPE_CHOICES = (
        (1, 'superuser'),
        (2, 'principaluser'),
        (3, 'teacheruser'),
    )

    user_type = models.PositiveSmallIntegerField(choices=USER_TYPE_CHOICES)


class School(models.Model):
    """School object"""

    name = models.CharField(max_length=255)
    users = models.ManyToManyField(settings.AUTH_USER_MODEL)


class Class(models.Model):
    """Class object"""

    name = models.CharField(max_length=255)
    users = models.ManyToManyField(settings.AUTH_USER_MODEL)
    school = models.ForeignKey(
        School,
        on_delete=models.CASCADE
    )


class Student(models.Model):
    """Person object"""

    fullname = models.CharField(max_length=255)
    class = models.ForeignKey(
        Class,
        on_delete=models.CASCADE
    )
...