首页 > 解决方案 > Django Auth:如何创建多对多关系模型?

问题描述

django.contrib.auth.models根据文档代码,只有 3 个模型、UserGroup、。Permission

Doc确实说groups并且permissions是多对多的关系。

但是当我们migrate如何创建其他关系user_group时?user_permissionsgroup_permissions

标签: djangodjango-modelsdjango-auth-models

解决方案


ManyToMany 关系的表是由models.ManyToManyField迁移文件中带有字符串的行创建的。

在这种情况下,它们是由初始迁移创建的django/contrib/auth/migrations/0001_initial.py。它与 非常相似django/contrib/auth/models.py

相关的SQL命令可以通过

$ python manage.py sqlmigrate auth 0001_initial

请参阅以下行:
CREATE TABLE "auth_user_groups"...
CREATE TABLE "auth_group_permissions"...
CREATE TABLE "auth_user_user_permissions"...

特别有趣的两篇文字都围绕着这个词REFERENCES。那是基表的外键,例如:
... "user_id" integer NOT NULL REFERENCES "auth_user" ("id") ...


编辑

您可能知道 ManyToMany 关系由参数through=SomeModel指定的显式中间模型和一个额外的字段连接。

我在示例中解释了如何在代码中使用隐藏的中间表

想象一下,您想记下某些权限,为什么您将其添加给某个人。

您可以从命令行探索模型结构,因为在“auth/models.py”中您只能读取名称“user_parmissions”。

>>> User._meta.local_many_to_many
[<django.db.models.fields.related.ManyToManyField: groups>,
 <django.db.models.fields.related.ManyToManyField: user_permissions>]
>>> User.user_permissions.through
<class 'django.contrib.auth.models.User_user_permissions'>
>>> User.user_permissions.through._meta.local_fields
[<django.db.models.fields.AutoField: id>,
 <django.db.models.fields.related.ForeignKey: user>,
 <django.db.models.fields.related.ForeignKey: permission>]

your_app/models.py

from django.contrib.auth.models import User, Group, Permission
from django.db import models

# This line is instead of import, because the implicit intermediate table
# can not be imported.
UserPermission = User.user_permissions.through

class UserPermissionReason(models.Model)
    user_permission = models.ForeignKey(UserPermission, ...)
    reason = models.CharField(help_text="Why I added that permission", ...)

makemigrations,迁移,壳...

示例:使用您的笔记创建用户权限

>>> from your_app.models import UserPermissionReason, UserPermission
>>> from django.contrib.auth.models import User, Group, Permission
>>> permission = Permission.objects.get(name='Can add user',
                                        content_type__app_label='auth')
>>> permission
<Permission: auth | user | Can add user>
>>> user_permission = UserPermission.objects.create(user=me_superuser,
                                                    permission=permission)
>>> why = UserPermissionReason.objects.create(
        user_permission=user_permission,
        reason="Because I can :-)"
    )

如果您不需要引用中间表,则可以使用普通的简单表some_ruser.user_permissions.add(permission)


推荐阅读