0

Is there a solution to get the app context in a class that inherit werkzeug BaseConverter class?

This is my example running in Flask:

from werkzeug.routing import BaseConverter
class CodeConverter(BaseConverter):
    app = None
    
    def to_python(self, value):
        # Create an app context to get value from db
        # and instantiate a class X as obj
        return obj
    
    def to_url(self, obj):
        value = obj.code
        title = obj.title
        return "%s/%s"%(value, title)

def crate_app():
    ...
    app.url_map.converters['code'] = CodeConverter
    CodeConverter.app = app
    ...
go-pera
  • 31
  • 2
  • I think `current_app` should work in both Flask and Quart (a recent change in both if I remember correctly) - does it? – pgjones Jul 17 '20 at 09:17
  • The problem is that the `app_context()` is an 'awaitable' function but `to_python` is not and I cannot call it. – go-pera Jul 17 '20 at 13:00
  • I don't think you'd need to call `app_context()` - are you trying to do something like `current_app.db.execute(...)` in the `to_python`? – pgjones Jul 18 '20 at 19:31
  • Yes, I tried, but the error is a 'RunTimeError: Attempt to access app outside of a relevant context'. This is why I think I need to push a context previously. – go-pera Jul 20 '20 at 13:38

1 Answers1

0

Well, this works for me.

from werkzeug.routing import BaseConverter
class CodeConverter(BaseConverter):
    app = None

    async def get_object(self, app, value):
        async with app.app_context():
            # and instantiate a class X as obj
            return obj

    def to_python(self, value):
        pool = concurrent.futures.ThreadPoolExecutor()
        result = pool.submit(asyncio.run, self.get_object(self.__class__.app, value)).result()
        return result

    def to_url(self, obj):
        value = obj.code
        title = obj.title
        return "%s/%s"%(value, title)

def crate_app():
    ...
    app.url_map.converters['code'] = CodeConverter
    CodeConverter.app = app
    ...
go-pera
  • 31
  • 2