首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >我怎样才能使这个Flask应用程序更干燥(连接到许多oauth )?

我怎样才能使这个Flask应用程序更干燥(连接到许多oauth )?
EN

Stack Overflow用户
提问于 2013-12-01 23:59:59
回答 1查看 603关注 0票数 2

我正在连接几个API(例如Twitter、GitHub等)。使用Flask-oauthlib。目前,我把每项服务都作为一个单独的蓝图。在每个服务的视图文件中,都有相同的三个视图:loginauthorizedget_token。现在的代码不是很枯燥,但我很难理解如何集中这些视图(更多的概念)。

,我怎么才能把这个弄干呢?我希望从概念上更好地理解,而不是真正为我编写代码。

下面是一些可能有帮助的项目。这是应用程序结构:

代码语言:javascript
复制
- App
    - Services
        - FourSquare BP
        - GitHub BP
        - Twitter BP
        - ...
    - Other BPs

泛型API视图可能在Services/api_views.py下。

下面是一个API Blueprint视图文件(Twitter)的示例。

代码语言:javascript
复制
twitter = Blueprint('twitter', __name__, url_prefix='/twitter')
bp = twitter

bp.api = TwitterAPI()
bp.oauth = bp.api.oauth_app

# Below here is the exact same for each file.

@bp.route('/')
@login_required
def login():
    if current_user.get(bp.name, None):
        return redirect(url_for('frontend.index'))
    return bp.oauth.authorize(callback=url_for('.authorized', _external=True))

@bp.route('/authorized')
@bp.oauth.authorized_handler
def authorized(resp):
    if resp is None:
        flash(u'You denied the request to sign in.')
        return redirect(url_for('frontend.index'))

    if bp.oauth_type == 'oauth2':
        resp['access_token'] = (resp['access_token'], '') 

    current_user[bp.name] = resp
    current_user.save()

    flash('You were signed in to %s' % bp.name.capitalize())
    return redirect(url_for('frontend.index'))

@bp.oauth.tokengetter
def get_token(token=None):
    if bp.oauth_type == 'oauth2':
        return current_user.get(bp.name, None)['access_token']
    return current_user.get(bp.name, None)['oauth_token']

我试着把视图放在一个类中,然后导入这些视图,但是在不同的装饰器上遇到了麻烦( oauth装饰师给出了最大的麻烦)。

EN

回答 1

Stack Overflow用户

发布于 2013-12-05 01:38:32

我想出了一个解决上述问题的好办法。请让我知道这是否一个好的解决办法。

我决定使用基于烧瓶类的视图。这样我就可以为上面的每个主要API函数创建一个类视图了:

代码语言:javascript
复制
class APILoginView(View):
    decorators = [login_required]

    def __init__(self, blueprint):
        self.blueprint = blueprint

    def dispatch_request(self):
        if current_user.get(self.blueprint.name, None):
            return redirect(url_for('frontend.index'))
        return self.blueprint.oauth.authorize(callback=url_for('.authorized', _external=True))

class APIAuthorizedView(View):
    decorators = [login_required]

    def __init__(self, blueprint):
        self.blueprint = blueprint

    def dispatch_request(self, resp):
        if resp is None:
            flash(u'You denied the request to sign in.')
            return redirect(url_for('frontend.index'))

        if self.blueprint.api.oauth_type == 'oauth2':
            resp['access_token'] = (resp['access_token'], '') #need to make it a tuple for oauth2 requests

        current_user[self.blueprint.name] = resp
        current_user.save()

        flash('You were signed in to %s' % self.blueprint.name.capitalize())
        return redirect(url_for('frontend.index'))

那是比较容易的部分。更棘手的事情是弄清楚如何泛化tokengetter,这是烧瓶OAuthLib库所必需的。以下是我最后得到的结果:

代码语言:javascript
复制
class APIToken():
    def __init__(self, blueprint):
        self.blueprint = blueprint

    def get_token(self, token=None):
        if self.blueprint.api.oauth_type == 'oauth2':
            return current_user.get(self.blueprint.name, None)['access_token']
        return current_user.get(self.blueprint.name, None)['oauth_token']

最后,创建一个函数来在蓝图上注册这些视图:

代码语言:javascript
复制
def registerAPIViews(blueprint):
    login_view = APILoginView.as_view('login', blueprint=blueprint)
    auth_view = blueprint.oauth.authorized_handler(
                        APIAuthorizedView.as_view('authorized', blueprint=blueprint))

    blueprint.add_url_rule('/', view_func=login_view)
    blueprint.add_url_rule('/authorized', view_func=auth_view)

    apiToken = APIToken(blueprint)
    token_getter = blueprint.oauth.tokengetter(apiToken.get_token)

    return blueprint
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20318812

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档