Обеспечение уникальности в нескольких моделях Django

У меня есть три модели: Счет, Сотрудник и Компания. Счет может быть типа сотрудник или компания, а поле OneToOne Field связывает счет с записью сотрудника или компании. См. модели ниже:

class Account(auth_models.AbstractBaseUser):

     username = models.CharField(max_length=40, unique=True)

     ACCOUNT_TYPE_CHOICES = (
         ("company", "Company"),
         ("employee", "Employee"),
     )

     account_type = models.CharField(
         choices=ACCOUNT_TYPE_CHOICES,
         default="EMPLOYEE",
         blank=False,
         null=False,
         max_length=10,
      )
     date_joined = models.DateTimeField(verbose_name="Date Joined", auto_now_add=True)
     is_active = models.BooleanField(default=True)
     is_superuser = models.BooleanField(default=False)

     USERNAME_FIELD = "username"
     REQUIRED_FIELDS = ["account_type"]

У меня есть модель компании:

class Company(models.Model):
    user = models.OneToOneField(Account, on_delete=models.CASCADE, unique=True)
    name = models.CharField(max_length=75, blank=False, null=False, unique=True)

Затем у меня есть модель Employee, где сотрудник также связан с компанией, в которой он работает:

class Employee(models.Model):
     user = models.OneToOneField(Account, on_delete=models.CASCADE, unique=True)
     first_name = models.CharField(max_length=50, null=False, blank=False)
     last_name = models.CharField(max_length=50, null=False, blank=False)
     date_of_birth = models.DateField(null=False, blank=False)
     employer = models.ForeignKey(
         Company, on_delete=models.CASCADE, related_name="employees"
     )
     employment_start_date = models.DateField(null=False, blank=False)
     employment_end_date = models.DateField(blank=True, null=True)

Я хочу убедиться, что имена пользователей уникальны в пределах компании, но не уникальны в пределах всего веб-приложения. Таким образом, может быть несколько пользователей с одинаковым именем пользователя, но не в пределах одной компании. Например: Предположим, пользователь создал учетную запись username John Smith с именем company ABC, что будет нормально.

Но тогда если другой пользователь создал аккаунт с username John Smith, но в company DEF, то это тоже будет разрешено, так как он находится в другой компании.

Но если кто-то попытается сделать счет с username John Smith внутри company ABC, это не будет разрешено, так как он уже существует в этой компании

Решения, которые я придумал на данный момент:

  1. Добавление поля company в модель Account - проблема в том, что Account с типом account_type "Company" не будет иметь значения для поля company, это было бы нелогично. Также это было бы нелогично, поскольку через отношения вы можете найти компанию, к которой принадлежит сотрудник, в таблице/модели Employee.
  2. .
  3. Получение поля "employees" из модели Company и проверка, существует ли пользователь уже в этом поле, так как оно эксклюзивно для компании - я понятия не имею, как реализовать что-то подобное.
  4. Использование электронной почты вместо этого - я хотел изначально сделать это, но люди в моей команде хотят, чтобы мы использовали имена пользователей вместо этого, так как не все, кто взаимодействует с системой, будут иметь электронную почту.

Любая помощь о том, как я могу реализовать что-то подобное, была бы замечательной. Спасибо :)

P.S Я использую Postgres

  1. Добавление поля company в модель Account - проблема в том, что Account с типом account_type "Company" не будет иметь значения для поля company, это было бы нелогично. Также это было бы нелогично, поскольку через отношения вы можете найти компанию, к которой принадлежит сотрудник, в таблице/модели Employee.
  2. .

Зачем компании иметь пустое поле компании? ОП может иметь его и с полем компании, поскольку у ОП есть поле account_type для различения типов счетов (обычно я предпочитаю иметь поля, подобные account_type, как Boolean, так что что-то вроде is_company).

Кроме того, OP не сможет найти компанию, к которой принадлежит сотрудник, из модели Employee, если OP удалит работодателя и примет, что работодатель неявно связан с компанией Account. Поэтому, если ОП примет этот подход, то удалите и его. (Ну, OP может, но тогда OP придется пройти через пользователя/аккаунт).


  1. Получение поля "employees" из модели Company и проверка, существует ли пользователь уже в этом поле, поскольку оно эксклюзивно для компании - я понятия не имею, как реализовать что-то подобное.

OP может использовать unique_together к модели Employee, как

class Meta:
        unique_together = [["employer", "user__username"]]

Все равно это не решает проблему того, что сначала создается счет, а потом банкомат сотрудника.

Поскольку для создания аккаунта OP уже проверяет уникальность имени пользователя, уникальность навязывается до сотрудника.

Как упоминает AKK, существует обходной путь для этого. Точнее, создание Счета и Сотрудника в транзакции . Это подразумевает, что OP может удалить unique=True в Accounts, что, согласно документации

Поле должно быть уникальным (т.е. в его определении должно быть установлено значение unique=True), если только вы не используете пользовательский бэкенд аутентификации, который может поддерживать неуникальные имена пользователей.


  1. Использование электронной почты - изначально я хотел сделать это, но люди в моей команде хотят, чтобы мы использовали имена пользователей, поскольку не у всех, кто взаимодействует с системой, будет электронная почта.

Ну, люди в команде OP могут не знать о последствиях, которые влечет за собой такой запрос. Хотя такой фреймворк, как Django, обеспечивает гибкость на различных уровнях, таких как миграция баз данных, он также имеет свои пути, которые могут быть неизвестны вашей команде. Вы можете провести встречу и представить различные варианты, которые рассматривал ОП, и их последствия, и я уверен, что они смогут понять.

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