Python 如何使用eve sqlalchemy更新项目关系

Python 如何使用eve sqlalchemy更新项目关系,python,sqlalchemy,eve,Python,Sqlalchemy,Eve,我创建了一个简单的eve sqlalchemy应用程序,它有一个用户和角色资源来模拟。User类可以有多个角色。下面提供了完整的示例代码 我感兴趣的是能够发布具有角色的用户,或者修补用户的角色。我一直无法找到一种不出错的方法 似乎eve sqlalchemy将User.roles的类型强制为整数,这是Role类的主键id。如果我将POST或PATCH请求设置为roles字段为整数,eve sqlalchemy抱怨userroles关联表不存在于self.driver.app.config['SO

我创建了一个简单的
eve sqlalchemy
应用程序,它有一个
用户
角色
资源来模拟。
User
类可以有多个角色。下面提供了完整的示例代码

我感兴趣的是能够
发布具有角色的
用户,或者
修补
用户的角色。我一直无法找到一种不出错的方法

似乎
eve sqlalchemy
User.roles
的类型强制为整数,这是
Role
类的主键
id
。如果我将
POST
PATCH
请求设置为
roles
字段为整数,
eve sqlalchemy
抱怨
userroles
关联表不存在于
self.driver.app.config['SOURCES']
中。虽然我可以进行这些更改(即将
userroles
表设置为声明性ORM并向decorator注册),但我不确定这样做是否正确

总之,
eve sqlalchemy
如何期望我用
角色列表发布
用户
,或
补丁
用户的现有角色

服务器: 请求:
我最后做的是:

  • userroles\u table
    从表转换为声明类
    UserRole
  • 使用
    eve\u sqlalchemy注册
    UserRole
  • 用户角色
    添加到
  • 然后可以通过新的资源端点
    用户角色
    直接查询或修改关联表
    eve_sqlalchemy
    在生成模式时会隐藏外键,因此包含与外键的关系很重要

    from eve import Eve
    from eve.utils import config
    
    from sqlalchemy import create_engine, Table, Column, String, Integer, ForeignKey, func, DateTime
    from sqlalchemy.ext.declarative import declarative_base
    from sqlalchemy.orm import relationship, sessionmaker
    
    from eve_sqlalchemy.decorators import registerSchema
    from eve_sqlalchemy import SQL
    from eve_sqlalchemy.validation import ValidatorSQL
    
    
    ID_FIELD = 'id'
    SQLALCHEMY_DATABASE_URI = 'sqlite:////tmp/eve-sqla-test.db'
    
    
    config.ID_FIELD = ID_FIELD
    config.ITEM_LOOKUP_FIELD = ID_FIELD
    
    
    Base = declarative_base()
    
    
    userroles_table = Table('userroles', Base.metadata,
        Column('user_id', Integer, ForeignKey("users.id"), primary_key=True),
        Column('role_id', Integer, ForeignKey("roles.id"), primary_key=True)
    )
    
    
    class CommonColumns(Base):
        __abstract__ = True
        _created = Column(DateTime, default=func.now())
        _updated = Column(DateTime, default=func.now(), onupdate=func.now())
        _etag = Column(String(40))
    
    
    class Role(CommonColumns):
        __tablename__ = 'roles'
        id = Column(Integer, primary_key=True, autoincrement=True)
        role = Column(String, unique=True, nullable=False)
    
    
    class User(CommonColumns):
        __tablename__ = 'users'
    
        id = Column(Integer, primary_key=True, autoincrement=True)
        login = Column(String, unique=True, nullable=False)
        roles = relationship("Role", backref="users", secondary=userroles_table)
    
    
    def create_entries():
        '''Creates test entries for querying with eve'''
        engine = create_engine(SQLALCHEMY_DATABASE_URI)
    
        Base.metadata.bind = engine
        Base.metadata.create_all()
    
        SessionMaker = sessionmaker(bind=engine)
        s = SessionMaker()
    
        u1 = User(login='user1')
        u1.roles.append(Role(role='admin'))
    
        u2 = User(login='user2')
        u2.roles.append(Role(role='user'))
    
        s.add_all((u1, u2))
        s.commit()
    
    
    def run():
        '''Runs the eve server'''
    
        for table in (User, Role):
            registerSchema(table.__tablename__)(table)
    
        users = User._eve_schema[User.__tablename__]
        users.update({
            'item_methods': ['GET', 'PATCH', 'DELETE'],
            'resource_methods': ['GET', 'POST'],
        })
    
        roles = Role._eve_schema[Role.__tablename__]
        roles.update({
            'resource_methods': ['GET', 'POST'],
        })
    
        DOMAIN = {
            'users': users,
            'roles': roles,
        }
    
        SETTINGS = {
            'SQLALCHEMY_DATABASE_URI': SQLALCHEMY_DATABASE_URI,
            'SQLALCHEMY_TRACK_MODIFICATIONS': False,
            'ID_FIELD': ID_FIELD,
            'ITEM_LOOKUP_FIELD': ID_FIELD,
            'DOMAIN': DOMAIN,
        }
    
        app = Eve(validator=ValidatorSQL, data=SQL, settings=SETTINGS)
    
        db = app.data.driver
        Base.metadata.bind = db.engine
        db.Model = Base
    
        app.run(debug=True)
    
    
    if __name__ == '__main__':
        '''Test area'''
    
        #create_entries()
        run()
    
    import json
    
    import requests
    
    
    u4 = {
       'login': 'user4',
    }
    
    
    # users get works
    r = requests.get('http://localhost:5000/users')
    print(r.text)
    
    
    # user creation works
    r = requests.post('http://localhost:5000/users', json=u4)
    print(r.text)
    
    
    # roles get works
    r = requests.get('http://localhost:5000/roles')
    print(r.text)
    
    
    # user creation with roles fail
    u5 = {
       'login': 'user5',
       'roles': [1,]
    }
    
    r = requests.post('http://localhost:5000/users', json=u5)
    print(r.text)  # {"_issues": {"roles": ["field 'roles' could not be coerced", "must be of integer type"]}, "_status": "ERR"}
    
    
    # user patch with role fails
    r = requests.get('http://localhost:5000/users/1')
    patch_headers = {"If-Match": r.json()['_etag'], 'Content-type': 'application/json; charset=utf-8'}
    
    r = requests.patch('http://localhost:5000/users/1', headers=patch_headers, json={'roles': [1,]})
    print(r.text)  # {"_issues": {"roles": ["field 'roles' could not be coerced", "must be of integer type"]}, "_status": "ERR"}