I can use below code to control the authority of menu 15,the role_id’s is_edit
is 1, the use can change the data in that menu, or user doesn’t have access to change/edit data,but the code is ugly, and I only can control one menu.
user_base = db.session.query(
UserBase.id,
UserBase.username,
UserBase.position_id,
UserBasePosition.role_id,
UserBasePosition.dep_id,
UserBasePosition.positional_title_id,
UserBasePosition.position_status,
UserBasePosition.view_range,
BaseMenuAuthority.menu_id,
BaseMenuAuthority.is_edit
).join(
UserBasePosition,
UserBase.position_id == UserBasePosition.id
).join(
BaseMenuAuthority,
UserBasePosition.role_id == BaseMenuAuthority.role_id
).filter(UserBase.id == user_id, BaseMenuAuthority.menu_id == 15).one()
@role_accepted(1)
def put(self):
# change something on Menu_15
How to control all menu? Maybe they look like this?
@role_accepted(1,1)
def put(self):
# change something on Menu_1
@role_accepted(2,1)
def put(self):
# change something on Menu_2
@role_accepted(3,1)
def put(self):
# change something on Menu_3
@role_accepted(4,1)
def put(self):
# change something on Menu_4
I tried to write code as below, but if I didn’t filter BaseMenuAuthority.menu_id
, I will got the error of sqlalchemy.orm.exc.MultipleResultsFound: Multiple rows were found for one()
user_base = db.session.query(
UserBase.id,
UserBase.username,
UserBase.position_id,
UserBasePosition.role_id,
UserBasePosition.dep_id,
UserBasePosition.positional_title_id,
UserBasePosition.position_status,
UserBasePosition.view_range,
BaseMenuAuthority.menu_id,
BaseMenuAuthority.is_edit
).join(
UserBasePosition,
UserBase.position_id == UserBasePosition.id
).join(
BaseMenuAuthority,
UserBasePosition.role_id == BaseMenuAuthority.role_id
).filter(UserBase.id == user_id).one()
Advertisement
Answer
Your code seems to work as expected. Clearly, without the filter by menu_id
there might be more than 1 row returned, and according to the documentation on sqlalchemy.orm.Query.one
, the MultipleResultsFound
exception is expected to be raised.
It looks to me that you could re-use the code of the query without (yet) executing it.
user_base_query = db.session.query(
UserBase.id,
UserBase.username,
UserBase.position_id,
UserBasePosition.role_id,
UserBasePosition.dep_id,
UserBasePosition.positional_title_id,
UserBasePosition.position_status,
UserBasePosition.view_range,
BaseMenuAuthority.menu_id,
BaseMenuAuthority.is_edit
).join(
UserBasePosition,
UserBase.position_id == UserBasePosition.id
).join(
BaseMenuAuthority,
UserBasePosition.role_id == BaseMenuAuthority.role_id
).filter(UserBase.id == user_id) # NOTE that .one() is removed
when you need to actually use it, you could just amend the query and execute as below
user_menu = user_base_query.filter(BaseMenuAuthority.menu_id == 15).one()
In fact, you could even make a helper function:
def get_user_menu(user_id: int, menu_id: int):
res = db.session.query(
UserBase.id,
UserBase.username,
UserBase.position_id,
UserBasePosition.role_id,
UserBasePosition.dep_id,
UserBasePosition.positional_title_id,
UserBasePosition.position_status,
UserBasePosition.view_range,
BaseMenuAuthority.menu_id,
BaseMenuAuthority.is_edit
).join(
UserBasePosition,
UserBase.position_id == UserBasePosition.id
).join(
BaseMenuAuthority,
UserBasePosition.role_id == BaseMenuAuthority.role_id
).filter(UserBase.id == user_id).filter(BaseMenuAuthority.menu_id == menu_id).one()