Django 中 3 个表之间的多对多关系
Many-to-many relationship between 3 tables in 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
的数据库 table 如下所示:
*--------*----------------*---------------------*
| ID | project_id | user_account_id |
*--------*----------------*---------------------*
我想在 project_users
field/table 中与 Discipline
模型建立额外的关系。这在 Django 中可能吗?我一直在 Django 中查看 intermediary-manytomany relationships,但这并不是我想要的。在我的应用程序中,有一定数量的学科,我想要实现的是在单个项目中为每个用户提供多个学科。所以像这样:
*--------*----------------*---------------------*-------------------*
| ID | project_id | user_account_id | discipline_id |
*--------*----------------*---------------------*-------------------*
这可能吗?
您可以创建一个模式来引用这三个模型,这实际上是 ManyToManyField
在幕后所做的:在两者之间创建一个模型。
class <strong>UserProjectDiscipline</strong>(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
)
您现在可以使用 myuser.userprojectdiscipline_set.all()
、[=16= 访问 UserAccount
、Project
and/or Discipline
的 UserProjectDiscipline
] 和 mydiscipline.userprojectdiscipline_set.all()
.
此外,您可以定义跨越此 table 的 ManyToManyField
,这样很容易获得 Discipline
的相关 Project
,等等。与:
class Project(models.Model):
project_name = models.CharField(max_length=50)
users = models.ManyToManyField(
'Users.UserAccount',
<strong>through='UserProjectDiscipline'</strong>,
related_name='projects',
blank=True
)
disciplines = models.ManyToManyField(
'Discipline',
<strong>through='UserProjectDiscipline'</strong>,
related_name='projects',
blank=True
)
# …
class UserAccount(AbstractBaseUser, PermissionsMixin):
username = models.CharField(max_length=30, unique=True)
disciplines = models.ManyToManyField(
'Discipline',
<strong>through='UserProjectDiscipline'</strong>,
related_name='users',
blank=True
)
# …
然后这些将在 UserProjectDiscipline
的 table 上进行 JOIN 以有效检索给定项目等的用户。如果您需要 UserProjectDiscipline
的对象,您仍然可以使用例如 myproject.userprojectdiscipline_set.all()
.
如果您因此想要为用户 myuser
给定项目 myproject
三个学科,您可以添加这些学科:
UserProjectDiscipline.objects.bulk_create([
UserProjectDiscipline(user_account=<em>myuser</em>, project=<em>my_project</em>, discipline=<em>mydiscipline<sub>1</sub></em>),
UserProjectDiscipline(user_account=<em>myuser</em>, project=<em>my_project</em>, discipline=<em>mydiscipline<sub>2</sub></em>),
UserProjectDiscipline(user_account=<em>myuser</em>, project=<em>my_project</em>, discipline=<em>mydiscipline<sub>3</sub></em>)
])
我有以下型号:
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
的数据库 table 如下所示:
*--------*----------------*---------------------*
| ID | project_id | user_account_id |
*--------*----------------*---------------------*
我想在 project_users
field/table 中与 Discipline
模型建立额外的关系。这在 Django 中可能吗?我一直在 Django 中查看 intermediary-manytomany relationships,但这并不是我想要的。在我的应用程序中,有一定数量的学科,我想要实现的是在单个项目中为每个用户提供多个学科。所以像这样:
*--------*----------------*---------------------*-------------------*
| ID | project_id | user_account_id | discipline_id |
*--------*----------------*---------------------*-------------------*
这可能吗?
您可以创建一个模式来引用这三个模型,这实际上是 ManyToManyField
在幕后所做的:在两者之间创建一个模型。
class <strong>UserProjectDiscipline</strong>(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
)
您现在可以使用 myuser.userprojectdiscipline_set.all()
、[=16= 访问 UserAccount
、Project
and/or Discipline
的 UserProjectDiscipline
] 和 mydiscipline.userprojectdiscipline_set.all()
.
此外,您可以定义跨越此 table 的 ManyToManyField
,这样很容易获得 Discipline
的相关 Project
,等等。与:
class Project(models.Model):
project_name = models.CharField(max_length=50)
users = models.ManyToManyField(
'Users.UserAccount',
<strong>through='UserProjectDiscipline'</strong>,
related_name='projects',
blank=True
)
disciplines = models.ManyToManyField(
'Discipline',
<strong>through='UserProjectDiscipline'</strong>,
related_name='projects',
blank=True
)
# …
class UserAccount(AbstractBaseUser, PermissionsMixin):
username = models.CharField(max_length=30, unique=True)
disciplines = models.ManyToManyField(
'Discipline',
<strong>through='UserProjectDiscipline'</strong>,
related_name='users',
blank=True
)
# …
然后这些将在 UserProjectDiscipline
的 table 上进行 JOIN 以有效检索给定项目等的用户。如果您需要 UserProjectDiscipline
的对象,您仍然可以使用例如 myproject.userprojectdiscipline_set.all()
.
如果您因此想要为用户 myuser
给定项目 myproject
三个学科,您可以添加这些学科:
UserProjectDiscipline.objects.bulk_create([
UserProjectDiscipline(user_account=<em>myuser</em>, project=<em>my_project</em>, discipline=<em>mydiscipline<sub>1</sub></em>),
UserProjectDiscipline(user_account=<em>myuser</em>, project=<em>my_project</em>, discipline=<em>mydiscipline<sub>2</sub></em>),
UserProjectDiscipline(user_account=<em>myuser</em>, project=<em>my_project</em>, discipline=<em>mydiscipline<sub>3</sub></em>)
])