simon

simon

github

如何操纵Django的ManyToMany隐藏表

如何操纵 Django 的 ManyToMany 隐藏表#

Created: May 28, 2021 6:18 PM
Tags: ORM, Python

今天遇到一个提问,搜了下网上有讨论的,但没有人提出解决方案,然后研究了下,有值得记录下来的价值,下面我来详细说明。

Issue— 问题#

希望可以修改 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()

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

Background— 了解情况#

首先我们要先去数据库里查一下这个表的结构,虽然从逻辑上来推断,是一个 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 来指向这个表

Solutions— 解决方案#

  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

但当我们 run server 的时候后,出现了另一个报错

Untitled 1

研究了一下源码,是 run server 的时候会执行一个 system check,里面有一个 all model check,其中一个指标fields.E340。代表的是 —-

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

.

可见 Django 是不希望我们直接操作中间表的,确实这很容易出现数据错乱的问题。但有的时候我们需要实现一些 hack 的功能,就只好勉力而行。

  1. 解决启动错误

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

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

至此,run server 一切正常,可以操作了

Untitled 2

References - 参考#

  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/
加载中...
此文章数据所有权由区块链加密技术和智能合约保障仅归创作者所有。