SQLAlchemy Falcon Class error

Я пытаюсь настроить API, используя Falcon и SQLAlchemy, используя базу данных postgresql. Использование gunicorn для запуска API

Я получаю следующую ошибку при попытке доступа к /v1/users.

Я пытался просмотреть документацию по SQLAlchemy, но не смог найти никакого работающего решения.

Спасибо

[2017-03-15 10:20:26 +0100] [20516] [ERROR] Error handling request /v1/users
    Traceback (most recent call last):
      File "/Users/juliencourtes/Documents/projects/FalconAPI/venv/lib/python3.6/site-packages/gunicorn/workers/sync.py", line 135, in handle
        self.handle_request(listener, req, client, addr)
      File "/Users/juliencourtes/Documents/projects/FalconAPI/venv/lib/python3.6/site-packages/gunicorn/workers/sync.py", line 176, in handle_request
        respiter = self.wsgi(environ, resp.start_response)
      File "/Users/juliencourtes/Documents/projects/FalconAPI/venv/lib/python3.6/site-packages/falcon/api.py", line 209, in __call__
        responder(req, resp, **params)
      File "/Users/juliencourtes/Documents/projects/FalconAPI/app/api/v1/users.py", line 50, in on_get
        users = session.query(User).all()
      File "/Users/juliencourtes/Documents/projects/FalconAPI/venv/lib/python3.6/site-packages/sqlalchemy/orm/scoping.py", line 157, in do
        return getattr(self.registry(), name)(*args, **kwargs)
      File "/Users/juliencourtes/Documents/projects/FalconAPI/venv/lib/python3.6/site-packages/sqlalchemy/orm/session.py", line 1330, in query
        return self._query_cls(entities, self, **kwargs)
      File "/Users/juliencourtes/Documents/projects/FalconAPI/venv/lib/python3.6/site-packages/sqlalchemy/orm/query.py", line 139, in __init__
        self._set_entities(entities)
      File "/Users/juliencourtes/Documents/projects/FalconAPI/venv/lib/python3.6/site-packages/sqlalchemy/orm/query.py", line 148, in _set_entities
        entity_wrapper(self, ent)
      File "/Users/juliencourtes/Documents/projects/FalconAPI/venv/lib/python3.6/site-packages/sqlalchemy/orm/query.py", line 3947, in __init__
        "expected - got '%r'" % (column, )
    sqlalchemy.exc.InvalidRequestError: SQL expression, column, or mapped entity expected - got '<function User at 0x1040216a8>'

Файлы моих проектов

main.py

import falcon
from app.api.v1 import users
from app.middleware import DatabaseSessionManager
from app.database import db_session, init_session
from app.api.common import base

class App(falcon.API):

    def __init__(self,*args, **kwargs):
        super(App, self).__init__(*args, **kwargs)
        self.add_route('/',base.BaseResource())
        self.add_route('/v1/users',users.Collection())


init_session()
mdlw = [DatabaseSessionManager(db_session)]
application = App(middleware=mdlw)

session.py

import sqlalchemy.orm.scoping as scoping
from sqlalchemy.exc import SQLAlchemyError

from app import config

class DatabaseSessionManager(object):
    def __init__(self, db_session):
        self._session_factory = db_session
        self._scoped = isinstance(db_session, scoping.ScopedSession)

    def process_request(self, req, res, resource=None):
        req.context['session'] = self._session_factory


    def process_response(self, req, res, resource=None):
        session = req.context['session']

        if config.DB_AUTOCOMMIT:
            try:
                session.commit()
            except SQLAlchemyError as ex:
                session.rollback()


        if self._scoped:
            session.remove()
        else:
            session.close()

база данных init.py

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, scoped_session
import psycopg2
from app import config


db_session = scoped_session(sessionmaker())
engine = create_engine('postgresql+psycopg2://xxxxx@localhost/falcon_api')


def init_session():
    db_session.configure(bind=engine)

user.py

from sqlalchemy import Column
from sqlalchemy import String, Integer,Text
from sqlalchemy.dialects.postgresql import UUID, JSONB
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

def User(Base):
    __tablename__ = 'user'

    id = Column('id', UUID, primary_key=True)
    firstname = Column('firstname', String)
    lastname = Column('lastname', String)

    #It tells python how to print the class, used for debugging
    def __repr__(self):
        return "<User(id='%s', name='%s', lastname='%s')>"% \
            (self.id, self.firstname, self.lastname)

    def __init__(self, id , firstname, lastname):
        self.id = id
        self.firstname = firstname
        self.lastname = lastname

апи /v1/users.py

import falcon
import json
from sqlalchemy.ext.declarative import declarative_base
try:
    from collections import OrderedDict
except ImportError:
    OrderedDict = dict
from app.models import User
class Collection():
    """
    Handle for endpoint: /v1/users
    """

    def to_json(self, body_dict):
        return json.dumps(body_dict)


    def on_error(self, resp, error=None):
        resp.status = error['status']
        meta = OrderedDict()
        meta['code'] = error['code']
        meta['message'] = error['message']

        obj = OrderedDict()
        obj['meta'] = meta
        resp.body = self.to_json(obj)

    def on_success(self, resp, data=None):
        resp.status = falcon.HTTP_200
        meta = OrderedDict()
        meta['code'] = 200
        meta['message'] = 'OK'

        obj = OrderedDict()
        obj['meta'] = meta
        obj['data'] = data
        resp.body = self.to_json(obj)


    def on_get(self, req, resp):
        session = req.context['session']

        #Bugging here
        users = session.query(User).all()

2 ответа

Я столкнулся с той же проблемой.. Это исправлено в моем случае для следующих изменений.. вместо session.remove() используйте следующий код.

if self._scoped:
     self._session_factory.remove()

Это будет работать

Мы создаем модели для SQL в python, используя Class, который наследует встроенный класс от ORM, например SQLAlchemy. Вот вы пытаетесь создать Userмодель. Но поскольку для правильной работы это должен быть класс, вместо этого вы объявили его как функцию в .

Все, что вам нужно сделать, чтобы заставить его работать, это просто изменить def Userк class User.

Так user.pyбудет выглядеть примерно так:

      ...
class User(Base):
    __tablename__ = 'user'
...
Другие вопросы по тегам