simon

simon

github

如何操作Django的ManyToMany隐藏表

如何操作 Django 的 ManyToMany 隐藏表#

创建日期:2021 年 5 月 28 日 下午 6:18
标签:ORM,Python

今天遇到一个问题,我在网上搜索了一下,虽然有一些讨论,但没有人提出解决方案。然后我自己研究了一下,发现有一些值得记录的东西,下面我会详细说明。

问题#

我希望能够修改 Django 默认的用户权限组表auth_user_groups,这个表可以通过User表进行操作。

from django.contrib.auth.models import User

u1 = User.objects.get(id=1)
u1.groups  # 这个就是其所在的auth user group的中间表
# 可以用以下方法添加group
u1.groups.add()

现在的需求是直接操作这个表,以便进行批量数据插入。

了解情况#

首先,我们需要在数据库中查看一下这个表的结构。虽然从逻辑上可以推断出它是一个包含 Group 表和 User 表外键字段的表(基于 Django 自动创建 ManyToMany 的规则)。

mysql> desc auth_user_groups;
+----------+---------+------+-----+---------+----------------+
| Field    | Type    | Null | Key | Default | Extra          |
+----------+---------+------+-----+---------+----------------+
| id       | int(11) | NO   | PRI | NULL    | auto_increment |
| user_id  | int(11) | NO   | MUL | NULL    |                |
| group_id | int(11) | NO   | MUL | NULL    |                |
+----------+---------+------+-----+---------+----------------+

正如我们所料,我们需要手动定义一个 model 来指向这个表。

解决方案#

  1. 自定义 model
from django.db import models as db
from django.contrib.auth.models import Group, User

class UserAuthGroup(db.Model):

    user = db.ForeignKey(User, on_delete=db.CASCADE)
    group = db.ForeignKey(Group, on_delete=db.CASCADE)

    class Meta:
        db_table = "auth_user_groups"  # 指定表名

通过以上步骤,我们可以在 Python Console 中操作这个表中的数据。

Untitled

但是当我们运行服务器时,出现了另一个错误。

Untitled 1

经过研究源代码,发现在运行服务器时会执行一个系统检查,其中包含一个 all model check,其中一个指标是fields.E340。它表示:

字段的中间表与表名 / 冲突。

.

显然,Django 不希望我们直接操作中间表,因为这很容易导致数据混乱的问题。但是有时我们需要实现一些 hack 的功能,只能尽力而为。

  1. 解决启动错误

解决方案是注释掉这个检查,在settings.py文件中添加以下内容:

SILENCED_SYSTEM_CHECKS = ["fields.E340"]  # 可以添加多个

通过以上步骤,运行服务器一切正常,可以进行操作。

Untitled 2

参考资料#

  1. http://c.biancheng.net/view/8001.html
  2. https://www.cnblogs.com/fengbo123/p/10837696.html
  3. https://www.pythonanywhere.com/forums/topic/14430/
  4. https://docs.djangoproject.com/en/3.2/ref/models/options/
載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。