实体关系模型设计与查询方法
Entity Relational Model Design and Query Method
当前设计:
用户和组:Many-to-Many Table
工具:SQLAlchemy 1.0.9,Python 2.7,金字塔
我向你提出的两个问题:
我不确定我是否应该在User
下有group
属性或user
属性在Group
。这是一个多对多的关系;第三个 table 与两个不同的 类 相关。
SQLAlchemy 有很多很好的例子讨论 .join
s,但我发现这个任务很难用这个数据库设计来根据选定的用户名进行查询。 (见下文)
我设计了一个 SQLAlchemy 数据库,并且正在尝试实施从我的 table 检索数据的最佳实践,同时消除冗余。话虽如此,我也希望这是一个有效的设计,这样当我使用 Pyramid's Authorization and Authentication System 构建 group_finder
函数时,我就没有问题了。
我正在使用 CRUD
方法。截至目前:要将 user
添加到 Group
,我 update_group_add_user(...)
添加用户或 update_group_remove_users(...)
删除用户。
base.py
注释掉 groups
并将 users
添加到 class Group
association_table = Table('group_user_link', Base.metadata,
Column('group_id', Integer, ForeignKey('groups.id')),
Column('user_id', Integer, ForeignKey('users.id')))
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
username = Column(String(15), nullable=False, unique=True)
email = Column(String(300))
password = Column(String(300), nullable=False)
#groups = relationship('Group', secondary='group_user_link', backref='users')
def __init__(self, username, password, firstname, lastname, email):
self.username = username
self.password = hashlib.sha224(password).hexdigest()
self.email = email
#self._groups = groups
def __repr__(self): # code
class Group(Base):
__tablename__ = 'groups'
id = Column(Integer, primary_key=True)
group_name = Column(String(50), unique=True)
users = relationship('User', secondary='group_user_link', backref='groups')
def __init__(self, group_name, user=None):
if user is None: user = []
self.group_name = group_name
self._user = user # to group_add_user and group_remove_user
def __repr__(self): # code
查询方法(使用CRUD):
这将打印出列表中元组中的所有关系。我只想打印出(和 return)正在输入的用户。
def retrieve_user_bygroup(self, username):
query= self.session.query(User, Group).join(association).\
filter(User.id == Group.id).\
order_by(User.id).all()
print "retrieve user by group:", query
return query
- 我会说
group
应该包含 [比方说] users
的 set
。反之则不然。
现在,您可能需要知道给定用户的组,如果您想将此映射缓存在内存中(而不是从数据库中获取),那么我建议不要在 group
和 user
class 是的。而是将该依赖项提升到第三个 class,它仅定义组和用户之间的关系。
例如
class user:
def __init__(self, name):
self.name = name
class group:
def __init__(self, name):
self.name = name
class user_group_relation:
def get_users(self, grp_name):
# could get it from an internal map (like return g2u_mapping[grp_name]) or
# run a query on some DB table..
pass
def get_group(self, usr_name):
# could get it from an internal map or run a query on some DB table..
pass
# group to user mapping
u2g_mapping = {user('user1'): group('group1'), user('user2'): group('group1')}
g2u_mapping = {group('group1'): [user('user1'), user('user2')]}
- 如果这是例如普通用户身份验证机制的表示,然后只有用户有密码,组没有。组只是一种组织事物的方式。因此,密码字段(以及任何相关功能应保留在用户中,而不是提升为基础。
我发现了两个类似的问题,它们阐明了 backref
、.join
和 .query
在 SQLAlchemy 中的用法。这有助于阐明在稍后使用 .join
和 .filter
(显示在底部)查询时,users = relationship('User', secondary='group_user_link', backref='groups')
中的 backref 行如何通过 User
访问 groups
。 =33=]
Discussing目的backref
:
backref means a 'poster' attribute will be added to UserPost. Actually
I'd probably call that 'user'. But the point is that 'relation()'
knows how to join between those two tables because of the previously
defined ForeignKey.
Discussing .join
和 .query
:
.join
[works] according [to] the relations, and yields 3-tuples. The arguments to
the query()
call are essentially the select list in sqlalchemy.
我还发现这个 Stacks answer 对使用 .any()
很有帮助
def retrieve_group_byuser(self, username):
# retrieves group by username
query = self.session.query(Group).\
filter(Group.users.any(User.username == username)).all()
print "retrieved by username:", query
return query
然后我从 User
中删除了 groups
,现在看起来像这样:
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
username = Column(String(15), nullable=False, unique=True)
email = Column(String(300))
password = Column(String(300), nullable=False)
def __init__(self, username, password, firstname, lastname, email):
self.username = username
self.password = hashlib.sha224(password).hexdigest()
self.email = email
def __repr__(self):
# code
当前设计:
用户和组:Many-to-Many Table
工具:SQLAlchemy 1.0.9,Python 2.7,金字塔
我向你提出的两个问题:
我不确定我是否应该在
User
下有group
属性或user
属性在Group
。这是一个多对多的关系;第三个 table 与两个不同的 类 相关。SQLAlchemy 有很多很好的例子讨论
.join
s,但我发现这个任务很难用这个数据库设计来根据选定的用户名进行查询。 (见下文)
我设计了一个 SQLAlchemy 数据库,并且正在尝试实施从我的 table 检索数据的最佳实践,同时消除冗余。话虽如此,我也希望这是一个有效的设计,这样当我使用 Pyramid's Authorization and Authentication System 构建 group_finder
函数时,我就没有问题了。
我正在使用 CRUD
方法。截至目前:要将 user
添加到 Group
,我 update_group_add_user(...)
添加用户或 update_group_remove_users(...)
删除用户。
base.py
注释掉 groups
并将 users
添加到 class Group
association_table = Table('group_user_link', Base.metadata,
Column('group_id', Integer, ForeignKey('groups.id')),
Column('user_id', Integer, ForeignKey('users.id')))
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
username = Column(String(15), nullable=False, unique=True)
email = Column(String(300))
password = Column(String(300), nullable=False)
#groups = relationship('Group', secondary='group_user_link', backref='users')
def __init__(self, username, password, firstname, lastname, email):
self.username = username
self.password = hashlib.sha224(password).hexdigest()
self.email = email
#self._groups = groups
def __repr__(self): # code
class Group(Base):
__tablename__ = 'groups'
id = Column(Integer, primary_key=True)
group_name = Column(String(50), unique=True)
users = relationship('User', secondary='group_user_link', backref='groups')
def __init__(self, group_name, user=None):
if user is None: user = []
self.group_name = group_name
self._user = user # to group_add_user and group_remove_user
def __repr__(self): # code
查询方法(使用CRUD):
这将打印出列表中元组中的所有关系。我只想打印出(和 return)正在输入的用户。
def retrieve_user_bygroup(self, username):
query= self.session.query(User, Group).join(association).\
filter(User.id == Group.id).\
order_by(User.id).all()
print "retrieve user by group:", query
return query
- 我会说
group
应该包含 [比方说]users
的set
。反之则不然。
现在,您可能需要知道给定用户的组,如果您想将此映射缓存在内存中(而不是从数据库中获取),那么我建议不要在 group
和 user
class 是的。而是将该依赖项提升到第三个 class,它仅定义组和用户之间的关系。
例如
class user:
def __init__(self, name):
self.name = name
class group:
def __init__(self, name):
self.name = name
class user_group_relation:
def get_users(self, grp_name):
# could get it from an internal map (like return g2u_mapping[grp_name]) or
# run a query on some DB table..
pass
def get_group(self, usr_name):
# could get it from an internal map or run a query on some DB table..
pass
# group to user mapping
u2g_mapping = {user('user1'): group('group1'), user('user2'): group('group1')}
g2u_mapping = {group('group1'): [user('user1'), user('user2')]}
- 如果这是例如普通用户身份验证机制的表示,然后只有用户有密码,组没有。组只是一种组织事物的方式。因此,密码字段(以及任何相关功能应保留在用户中,而不是提升为基础。
我发现了两个类似的问题,它们阐明了 backref
、.join
和 .query
在 SQLAlchemy 中的用法。这有助于阐明在稍后使用 .join
和 .filter
(显示在底部)查询时,users = relationship('User', secondary='group_user_link', backref='groups')
中的 backref 行如何通过 User
访问 groups
。 =33=]
Discussing目的backref
:
backref means a 'poster' attribute will be added to UserPost. Actually I'd probably call that 'user'. But the point is that 'relation()' knows how to join between those two tables because of the previously defined ForeignKey.
Discussing .join
和 .query
:
.join
[works] according [to] the relations, and yields 3-tuples. The arguments to thequery()
call are essentially the select list in sqlalchemy.
我还发现这个 Stacks answer 对使用 .any()
def retrieve_group_byuser(self, username):
# retrieves group by username
query = self.session.query(Group).\
filter(Group.users.any(User.username == username)).all()
print "retrieved by username:", query
return query
然后我从 User
中删除了 groups
,现在看起来像这样:
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
username = Column(String(15), nullable=False, unique=True)
email = Column(String(300))
password = Column(String(300), nullable=False)
def __init__(self, username, password, firstname, lastname, email):
self.username = username
self.password = hashlib.sha224(password).hexdigest()
self.email = email
def __repr__(self):
# code