简体   繁体   中英

Using request data outside of routing endpoint

I am using Flask for an API. In one of my routing endpoints, I want to use a model instance with the flask.request object's remote_user attribute for a default value.

The class definition of my model is:

class Results(db.Model):
    __tablename__ = 'results'
    id = Column(Integer, primary_key=True, autoincrement=True)
    sid = Column(Integer)
    attribute = Column(String(2048))
    value_s = Column(String(2048))
    value_d = Column(Float)
    user = Column(String(48), default=request.remote_user)

The problem is I need to define this class outside of the endpoint, but when I use the request object outside of an endpoint I get the error: RuntimeError: working outside of request context.

As a test, I tried defining the class in the endpoint, and it works for the first time I hit the endpoint and instantiated the model, but when I hit the endpoint after that I get an error that sqlalchemy.exc.InvalidRequestError: Table '[tablename]' is already defined for this MetaData instance. Specify 'extend_existing=True' to redefine options and columns on an existing Table object. sqlalchemy.exc.InvalidRequestError: Table '[tablename]' is already defined for this MetaData instance. Specify 'extend_existing=True' to redefine options and columns on an existing Table object.

I will need to use this model class in another endpoint, so how can I define my model class with the request object outside of the request context in my endpoint?

flask.request is a proxy that is valid only during a request. The models are added to MetaData on startup , so it tries to resolve the default value request.remote_address before a request is received.

When you move the model declaration to the api layer, the models are instantiated on every request, which throws an error since MetaData accepts only unique table names.

SQLAlchemy allows you to define a function as the default value of the field. The difference here is that the callable is executed only on insert or update. So if you define your field as:

user = Column(String(48), default=lambda: request.remote_user)

request gets resolved only when you interact with the db. The caveat with this is that you won't be able to use this model class when you're not in a request context.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM