我在使用 Flask、Flask-sqlalchemy 和 flask-marshmallow 创建多对多 postgresql 数据库表的条目时遇到问题。以下是我的模型设置。
role_permissions = db.Table(
'role_permissions',
db.Column('id', db.Integer, primary_key=True, autoincrement=True),
db.Column('role_id', db.Integer, db.ForeignKey(
'roles.id', ondelete='RESTRICT', onupdate='CASCADE')),
db.Column('permission_id', db.Integer,
db.ForeignKey('op_permission.id', ondelete='RESTRICT', onupdate='CASCADE')))
以下是各个表:角色和权限
class Role(db.Model):
__tablename__ = 'roles'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
name = db.Column(db.String(50), unique=True, nullable=False)
description = db.Column(db.String(100), nullable=True)
created_at = db.Column(db.DateTime, server_default=db.func.now())
updated_at = db.Column(db.DateTime, server_default=db.func.now(),
server_onupdate=db.func.now())
permissions = db.relationship(
"Permission", secondary=role_permissions, backref=db.backref('roles', lazy='joined'))
def __repr__(self):
return '<Role {}>'.format(self.name)
def has_id(self, id: int) -> bool:
if Role.query.filter_by(id=id).count():
return True
return False
def has_name(self, name: str) -> bool:
if Role.query.filter_by(name=name).count():
return True
return False
class Permission(db.Model):
"""
Model for permission such as GetWallet
a combination of Action and Service
"""
__tablename__ = 'op_permission'
id = db.Column(db.Integer(), primary_key=True, autoincrement=True)
service_id = db.Column(db.Integer(),
db.ForeignKey('op_service.id', ondelete='CASCADE'),
nullable=True)
service = db.relationship(Service)
action = db.Column(db.String(128), nullable=False, unique=True)
现在,当我尝试使用这个棉花糖模式和下面的视图向一个角色添加一组权限时(例如,我已经有一个管理员角色)
class RolePermissionsAPIView(FlaskView):
route_base = 'iam/roles/<id>/permissions'
""" Assign permissions to roles """
def post(self, id, **kwargs):
try:
role = Role.query.filter_by(id=id).first_or_404()
post_data = request.get_json()
role_perm = RolePermissionsCreateSchema(partial=True).load(post_data)
db.session.add(role_perm)
db.session.commit()
# also tried this
#role.permissions.append(role_perm.permissions)
#db.session.add(role)
#db.session.commit()
return jsonify(data=RoleSchema().dump(role), status=True), 201
except NotFound:
raise CustomException(
message="Role does not exist", status_code=400)
except marshmallow.exceptions.ValidationError as e:
raise CustomException(
message=dict(errors=e.messages), status_code=400)
对于反序列化的架构,我想传入一个现有权限 ID 列表以立即附加到一个角色。
class RolePermissionsCreateSchema(ma.ModelSchema):
permissions = fields.Pluck('PermissionListSchema', 'id', many=True)
class Meta:
model = Role
这是我在传递此数据时遇到的 422 Unprocessable entity 错误。
{
"id": 2,
"permissions": [1, 2]
}
我用谷歌搜索无济于事。可以和 psycopg2 一起使用吗?
Traceback (most recent call last):
File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 1612, in full_dispatch_request
rv = self.dispatch_request()
File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 1598, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/usr/local/lib/python3.7/site-packages/flask_classful.py", line 268, in proxy
response = view(**request.view_args)
File "/usr/local/lib/python3.7/site-packages/flask_classful.py", line 239, in inner
return fn(*args, **kwargs)
File "/usr/src/app/users/api/v2/roles.py", line 82, in post
db.session.commit()
File "<string>", line 2, in commit
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/orm/session.py", line 1428, in commit
self._transaction.commit(_to_root=self.future)
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/orm/session.py", line 829, in commit
self._prepare_impl()
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/orm/session.py", line 808, in _prepare_impl
self.session.flush()
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/orm/session.py", line 3340, in flush
self._flush(objects)
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/orm/session.py", line 3480, in _flush
transaction.rollback(_capture_exception=True)
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/util/langhelpers.py", line 72, in __exit__
with_traceback=exc_tb,
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/util/compat.py", line 207, in raise_
raise exception
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/orm/session.py", line 3440, in _flush
flush_context.execute()
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/orm/unitofwork.py", line 456, in execute
rec.execute(self)
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/orm/unitofwork.py", line 579, in execute
self.dependency_processor.process_saves(uow, states)
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/orm/dependency.py", line 1183, in process_saves
uowcommit, secondary_insert, secondary_update, secondary_delete
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/orm/dependency.py", line 1245, in _run_crud
connection.execute(statement, secondary_insert)
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/base.py", line 1286, in execute
return meth(self, multiparams, params, _EMPTY_EXECUTION_OPTS)
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/sql/elements.py", line 326, in _execute_on_connection
self, multiparams, params, execution_options
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/base.py", line 1488, in _execute_clauseelement
cache_hit=cache_hit,
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/base.py", line 1843, in _execute_context
e, statement, parameters, cursor, context
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/base.py", line 2027, in _handle_dbapi_exception
util.raise_(exc_info[1], with_traceback=exc_info[2])
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/util/compat.py", line 207, in raise_
raise exception
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/base.py", line 1780, in _execute_context
cursor, statement, parameters, context
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/dialects/postgresql/psycopg2.py", line 957, in do_executemany
**kwargs
TypeError: execute_values() got an unexpected keyword argument 'fetch'
将不胜感激任何帮助。