Django - модели с отношениями к возможно несуществующим пользователям

Я работаю над корпоративной LMS на базе REST-фреймворка Django.

Аутентификация осуществляется через Google OAuth 2.0 с использованием пакета drf-social-oauth2, а целевыми организациями для моего программного обеспечения являются школы и университеты.

Некоторые модели имеют внешние ключи к модели пользователя; однако, в силу особенностей моего приложения, часто пользователь может захотеть сослаться на пользователя, которого еще нет в базе данных. Это происходит потому, что пользователи создаются в базе данных при первом входе в приложение через OAuth, но человек, который хочет создать конкретный экземпляр модели, ссылающийся на другого пользователя, может захотеть сделать это до того, как он впервые войдет в систему: например, преподаватель может захотеть предварительно записать список студентов в свой новый курс, но эти пользователи могут еще не войти в систему в первый раз и поэтому могут не существовать в базе данных.

Приведу конкретный пример с моделью в моем приложении:

class UserCoursePrivilege(models.Model):
    """
    Represents the administrative permissions a user has over a course.
    See logic.privileges.py for the available permissions.
    """

    user = models.ForeignKey(
        User,
        on_delete=models.CASCADE,
        related_name="privileged_courses",
    )
    course = models.ForeignKey(
        Course,
        on_delete=models.CASCADE,
        related_name="privileged_users",
    )
    allow_privileges = models.JSONField(default=list, blank=True)
    deny_privileges = models.JSONField(default=list, blank=True)

Этот объект создается во фронтенде путем обращения к таблице, которая показывает всех зарегистрированных пользователей и позволяет включать переключатели, соответствующие определенным разрешениям для данного пользователя.

Не раз я оказывался в ситуации, когда учитель писал мне, что не может найти своего коллегу, чтобы добавить его права на курс, а я говорил, чтобы он сначала вошел в систему, а потом вернулся и нашел его в таблице пользователей.

Однако это не очень удобно для пользователя и как-то нелогично, учитывая, что мое приложение не предусматривает явного процесса создания пользователя, поэтому ментальная модель для пользователей заключается в том, что их учетная запись каким-то образом "уже существует" и им просто нужно войти.

Я ищу способ справиться с этим как можно более прозрачным способом. Целевой пользовательский опыт выглядит примерно так: если пользователь не может найти человека, для которого он хочет создать объект, интерфейс показывает ему баннер типа "Can't find the person you're looking for?" и позволяет ему ввести адрес электронной почты этого человека и продолжить как обычно (в приведенном выше примере это подразумевало бы показ всех переключателей для выбора разрешений для предоставления).

Затем будет создан экземпляр правильной модели, но с нулевым внешним ключом для пользователя. Тогда у меня будет модель, которая выглядит следующим образом:

class PendingModelInstance(models.Model):
    """
    Represents a model instance which references a user that doesn't exist yet
    """

    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
    object_id = models.TextField()
    content_object = GenericForeignKey("content_type", "object_id")

    email_address = models.TextField()

будет создан экземпляр, ссылающийся на "частичный" экземпляр с отсутствующим FK и адресом электронной почты пользователя.

Затем, при создании пользователя, выполняется запрос для получения всех экземпляров PendingModelInstance, которые имеют email вновь созданного пользователя, затем извлекаются их ссылочные модели и обновляются с FK для нового экземпляра пользователя.

Этот подход, кажется, может работать хорошо, но он вводит проблему, которая мне не очень нравится: он делает внешние ключи нулевыми, чего не нужно и не должно быть.

Есть ли лучшая альтернатива?

Вернуться на верх