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 для нового экземпляра пользователя.
Этот подход, кажется, может работать хорошо, но он вводит проблему, которая мне не очень нравится: он делает внешние ключи нулевыми, чего не нужно и не должно быть.
Есть ли лучшая альтернатива?