用户、组和角色的多对多声明式 SQLAlchemy 定义

2024-04-02

我是 SQLAlchemy 的新手,想知道定义此类表和关系的最佳方法是什么。我希望能够通过以下方式访问用户组user.groups,分组中的用户group.users,并找出用户在组中的角色(我假设将在关联模型中定义逻辑)。我还想按组选择所有用户,并包括角色标题。

我尝试使用教程创建关联表(声明式样式)并删除secondary论证relationship属性在User and Group类,但随后我将失去直接从用户访问组以及直接从组访问用户的能力(backref关联表中的 指向关联类本身:/)。

任何帮助,将不胜感激。


简化模型的关键是使用关联代理 http://www.sqlalchemy.org/docs/orm/extensions/associationproxy.html,因此您一定要检查一下。
假设user只能有一个role在一个组中,下面的代码应该可以回答您的所有问题:

  • 如何配置模型和关系
  • 如何添加/删除/更新角色
  • 如何检索您要求的数据(报告)

您应该接管模型部分并忘记其余部分。下面是完整包含的工作脚本:

from sqlalchemy import create_engine, Column, Integer, Unicode, ForeignKey
from sqlalchemy.orm import relationship, scoped_session, sessionmaker
from sqlalchemy.orm.collections import attribute_mapped_collection
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.ext.associationproxy import association_proxy

# Configure test data SA
engine = create_engine(u'sqlite:///:memory:', echo=False)
session = scoped_session(sessionmaker(bind=engine, autoflush=False))
Base = declarative_base()

class _BaseMixin(object):
    """
    A helper mixin class to set properties on object creation.

    Also provides a convenient default __repr__() function, but be aware that
    also relationships are printed, which might result in loading the relation
    objects from the database
    """
    def __init__(self, **kwargs):
        for k, v in kwargs.items():
            setattr(self, k, v)

    def __repr__(self):
        return "<%s(%s)>" % (self.__class__.__name__,
            ', '.join('%s=%r' % (k, self.__dict__[k])
                      for k in sorted(self.__dict__)
                      if '_' != k[0]
                      #if '_sa_' != k[:4] and '_backref_' != k[:9]
                      )
            )


# relation creator factory functions
def _creator_gr(group, role):
    res = UserGroup(group=group, role=role)
    return res
def _creator_ur(user, role):
    res = UserGroup(user=user, role=role)
    return res

##############################################################################
# Object Model
##############################################################################
class Role(Base, _BaseMixin):
    __tablename__ = 'roles'
    # columns
    id = Column(Integer, primary_key=True, autoincrement=True)
    name = Column(Unicode(16), unique=True)
    # relations
    usergroup = relationship("UserGroup", backref='role')

class User(Base, _BaseMixin):
    __tablename__ = 'users'
    # columns
    id = Column(Integer, primary_key=True, autoincrement=True)
    name = Column(Unicode(16), unique=True)
    # relations
    _rel_usergroup = relationship("UserGroup", collection_class=attribute_mapped_collection('group'),
                                  cascade='all,delete-orphan',
                                  backref='user',
                                  )
    groups = association_proxy('_rel_usergroup', 'role', creator=_creator_gr)

class Group(Base, _BaseMixin):
    __tablename__ = 'groups'
    # columns
    id = Column(Integer, primary_key=True, autoincrement=True)
    name = Column(Unicode(16), unique=True)
    # relations
    _rel_usergroup = relationship("UserGroup", collection_class=attribute_mapped_collection('user'),
                                  cascade='all,delete-orphan',
                                  backref='group',
                                  )
    users = association_proxy('_rel_usergroup', 'role', creator=_creator_ur)

class UserGroup(Base, _BaseMixin):
    __tablename__ = 'user_group'
    # columns
    id = Column(Integer, primary_key=True, autoincrement=True)
    user_id = Column(Integer, ForeignKey('users.id', ondelete='CASCADE'), nullable=False)
    group_id = Column(Integer, ForeignKey('groups.id', ondelete='CASCADE'), nullable=False)
    role_id = Column(Integer, ForeignKey('roles.id', ondelete='CASCADE'), nullable=False)
    # relations
    # (all backrefs)



##############################################################################
# TESTS (showing usages)
#
# Requirements:
#  - list all groups of the user: user.groups (use keys)
#  - list all users of the group: group.users (use keys)
#  - get all users ordered (grouped) by group with the role title
##############################################################################

def _requirement_get_user_groups(user):
    return user.groups.keys()

def _requirement_get_group_users(group):
    return group.users.keys()

def _requirement_get_all_users_by_group_with_role():
    qry = session.query(Group).order_by(Group.name)
    res = []
    for g in qry.all():
        for u, r in sorted(g.users.items()):
            value = (g.name, u.name, r.name)
            res.append(value)
    return res

def _test_all_requirements():
    print '--requirement: all-ordered:'
    for v in _requirement_get_all_users_by_group_with_role():
        print v

    print '--requirement: user-groups:'
    for v in session.query(User).order_by(User.id):
        print v, " has groups: ",  _requirement_get_user_groups(v)

    print '--requirement: group-users:'
    for v in session.query(Group).order_by(Group.id):
        print v, " has users: ",  _requirement_get_group_users(v)

# create db schema
Base.metadata.create_all(engine)

##############################################################################
# CREATE TEST DATA
##############################################################################

# create entities
u_peter = User(name='u_Peter')
u_sonja = User(name='u_Sonja')
g_sales = Group(name='g_Sales')
g_wales = Group(name='g_Wales')
r_super = Role(name='r_Super')
r_minor = Role(name='r_Minor')

# helper functions
def _get_entity(entity, name):
    return session.query(entity).filter_by(name=name).one()
def get_user(name):
    return _get_entity(User, name)
def get_group(name):
    return _get_entity(Group, name)
def _checkpoint():
    session.commit()
    session.expunge_all()
    _test_all_requirements()
    session.expunge_all()
    print '-' * 80


# test: **ADD**
u_peter.groups[g_wales] = r_minor # add
g_wales.users[u_sonja] = r_super # add
g_sales.users[u_peter] = r_minor # add
session.add(g_wales)
#session.add(g_sales)
_checkpoint()

# test: **UPDATE**
u_peter = get_user('u_Peter')
assert u_peter.name == 'u_Peter' and len(u_peter.groups) == 2
assert len(u_peter.groups) == 2
g_wales = get_group('g_Wales')
g_wales.users[u_peter] = r_super # update
_checkpoint()

# test: **DELETE**
u_peter = get_user('u_Peter')
assert u_peter.name == 'u_Peter' and len(u_peter.groups) == 2
g_wales = get_group('g_Wales')
del u_peter.groups[g_wales] # delete
_checkpoint()
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

用户、组和角色的多对多声明式 SQLAlchemy 定义 的相关文章

随机推荐

  • Serilog - 如何制作自定义控制台输出格式?

    我在用Serilog https github com serilog serilog with Serilog 接收器 控制台 https github com serilog serilog sinks console在我的 C 项目中
  • omn​​iauth-devise 错误:“验证失败:电子邮件已被占用”

    我正在尝试使用omniauth devise创建一个rails 4应用程序 使用 Facebook 登录 使用谷歌登录 使用 linkedin 登录 用推特登录 在这里 我可以使用 facebook linkedin twitter 或 g
  • 如何从 WooCommerce 店面主题主页隐藏页面标题?

    我试图隐藏主页上的店面页面标题 此代码从各个方面隐藏它 function sf change homepage title args remove action storefront page storefront page header
  • 如何做一个连续回收UIView动画

    下面的代码将图像视图从右向左移动一次 但我想连续这样做 从右向左移动 然后在屏幕外向左移回 然后再次从右向左重复 imageview UIImageView alloc initWithFrame CGRectMake 320 200 26
  • PHP 中的一行 if 语句

    我想要一些类似于 JavaScript 的东西 var foo true foo doSometing 但这似乎在 PHP 中不起作用 如果满足条件 我会尝试向标签添加一个类 并且为了可读性 我希望将嵌入的 PHP 保持在最低限度 到目前为
  • 如何做到“如果单击其他..”

    我正在尝试使用 jQuery 来做类似的事情 if jQuery id click do some stuff else run function2 但我不确定如何使用 jQuery 来做到这一点 任何帮助将不胜感激 Edit 我正在尝试运
  • 我们可以动态添加文本字段吗

    我在我的聊天机器人中创建了一个自适应卡 使用 json 它接受用户的输入 我想添加一个按钮 使用户每次单击插入字段时都可以添加新的文本字段 即 用户可以单击插入按钮输入教育详细信息 学校 学院等 这可以在自适应卡中实现吗 我也想知道 自适应
  • 在文本段中创建具有给定大小的 C 函数

    我正在编程一个嵌入式powerpc questions tagged powerpc32位系统具有32 kbyte 8路组相联二级指令缓存 为了避免缓存抖动 我们以某种方式对齐函数 使得高频调用的一组函数的文本 想想中断代码 最终出现在单独
  • 在 Flash 对象内滚动时防止网页滚动

    我确信这一定是一个常见问题 但我在其他地方没有找到答案 我在一个长网页中嵌入了一个 Flash 对象 我侦听 Flash 中的 MOUSE WHEEL 事件 并相应地滚动 Flash 内容 但是 当我滚动 Flash 对象时 网页也会滚动
  • CORS 在 wso2 身份服务器中被阻止

    我将 WSO2is 5 7 0 与我的 Angular 6 应用程序一起使用 我尝试从我的应用程序进行 api 调用 但出现 cors 错误 Cross Origin Request Blocked The Same Origin Poli
  • 使用 telephonyserivce.endcall() 在 android 中结束通话

    我正在开发一个应用程序 我想在其中结束拨出呼叫 这是主要课程 import android app Activity import android content ActivityNotFoundException import andro
  • iPhone 游戏开发者 - 你们的工具链是什么样的?

    例如 源代码控制 git adobe驱动 3d 谷歌sketchup gt dae gt 搅拌机 gt obj 2d photoshop illustrator gt png 音频 大胆 gt caf 代码 ArgoUML Xcode Te
  • 使用 xcworkspace 时一直收到 ld:找不到 -lBolts 的库

    你好 这是我的Podfile Uncomment this line to define a global platform for your project platform ios 8 4 Uncomment this line if
  • 如何更改微调器文本大小和文本颜色?

    在我的 Android 应用程序中 我使用 spinner 并且我已将 SQLite 数据库中的数据加载到 spinner 中 并且它工作正常 这是代码 Spinner spinner Spinner this findViewById R
  • 如何以与参考线本身相同的角度注释参考线?

    我需要找到一种方法以与参考线本身相同的角度注释参考线 以下语句将生成参考线及其上方的标签 但是 线的斜率可能会发生变化 我需要找到一种方法来确保注释始终处于相同的角度 plot 1 10 1 10 abline a 8 b 1 text x
  • 是否可以自定义使用 Spring Native(使用 buildpack)生成的 docker 镜像

    我目前正在开发一个 Spring Native 应用程序 它使用 paketo buildpack 进行构建并生成 Docker 映像 我想知道是否可以通过添加第三方工具 例如 Datadog 代理 来自定义生成的 Docker 映像 另外
  • 大十进制乘法

    我尝试将两个相乘BigDecimal价值观与multiply方法如下 BigDecimal dur BigDecimal valueOf 60 1 1 BigDecimal bal BigDecimal valueOf 1 1 BigDec
  • 如何在 Windows 中使用批处理脚本创建符号链接?

    我当前正在使用以下脚本将具有特定前缀的所有文件复制到目标目录 for f delims k in dir d Search Path File Prefix s b do copy k d Target Directory 这工作正常 但我
  • Rails 文件下载和查看更新 - Howto?

    这看起来应该是直截了当的 但我很难过 我有一个视图控制器的链接 最终使用 send data 将文件下载到用户的硬盘驱动器 这非常有效 并且它使当前视图显然没有受到影响 但现在我希望页面在下载完成后提供一些反馈 在调用 send data
  • 用户、组和角色的多对多声明式 SQLAlchemy 定义

    我是 SQLAlchemy 的新手 想知道定义此类表和关系的最佳方法是什么 我希望能够通过以下方式访问用户组user groups 分组中的用户group users 并找出用户在组中的角色 我假设将在关联模型中定义逻辑 我还想按组选择所有