Отношения "многие ко многим" между 3 таблицами в Django
У меня есть следующие модели:
class Project(models.Model):
project_name = models.CharField(max_length=50)
project_users = models.ManyToManyField('Users.UserAccount', related_name='project_users', blank=True)
....
class UserAccount(AbstractBaseUser, PermissionsMixin):
username = models.CharField(max_length=30, unique=True)
....
class Discipline(models.Model):
name = models.CharField(unique=True, max_length=27, choices=discipline_choices)
Таблица БД для project_users
выглядит следующим образом:
*--------*----------------*---------------------*
| ID | project_id | user_account_id |
*--------*----------------*---------------------*
Я хочу иметь дополнительную связь в project_users
поле/таблице с Discipline
моделью. Возможно ли это в Django? Я рассматривал в Django отношения посредник-манитомания, но это не совсем то, что мне нужно. В моем приложении есть определенное количество дисциплин, и я пытаюсь добиться того, чтобы дать каждому пользователю несколько дисциплин в одном проекте. Так что что-то вроде этого:
*--------*----------------*---------------------*-------------------*
| ID | project_id | user_account_id | discipline_id |
*--------*----------------*---------------------*-------------------*
Возможно ли это?
Вы можете сделать режим, который ссылается на три модели, это фактически то, что ManyToManyField
делает за занавесками: создает модель между ними.
class UserProjectDiscipline(models.Model):
user_account = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE
)
project = models.ForeignKey(
Project,
on_delete=models.CASCADE
)
discipline = models.ForeignKey(
Discipline,
on_delete=models.CASCADE
)
Теперь вы можете получить доступ к UserProjectDiscipline
в UserAccount
, Project
и/или Discipline
с помощью myuser.userprojectdiscipline_set.all()
, myproject.userprojectdiscipline_set.all()
и mydiscipline.userprojectdiscipline_set.all()
.
Кроме того, можно определить ManyToManyField
s, которые охватывают эту таблицу, так что легко получить связанные Project
s из Discipline
и т.д. с помощью:
class Project(models.Model):
project_name = models.CharField(max_length=50)
users = models.ManyToManyField(
'Users.UserAccount',
through='UserProjectDiscipline',
related_name='projects',
blank=True
)
disciplines = models.ManyToManyField(
'Discipline',
through='UserProjectDiscipline',
related_name='projects',
blank=True
)
# …
class UserAccount(AbstractBaseUser, PermissionsMixin):
username = models.CharField(max_length=30, unique=True)
disciplines = models.ManyToManyField(
'Discipline',
through='UserProjectDiscipline',
related_name='users',
blank=True
)
# …
Затем они будут делать JOINs на таблице UserProjectDiscipline
для получения эффективных пользователей для данного проекта и т.д. Если вам нужны объекты для UserProjectDiscipline
, вы можете использовать, например, myproject.userprojectdiscipline_set.all()
.
Если вы хотите дать пользователю myuser
три дисциплины для данного проекта myproject
, вы добавляете их с:
UserProjectDiscipline.objects.bulk_create([
UserProjectDiscipline(user_account=myuser, project=my_project, discipline=mydiscipline1),
UserProjectDiscipline(user_account=myuser, project=my_project, discipline=mydiscipline2),
UserProjectDiscipline(user_account=myuser, project=my_project, discipline=mydiscipline3)
])