国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

flask_login模塊中user_loader裝飾器引發(fā)的思考

A Loity / 3151人閱讀

摘要:最后我們看下這個(gè)方法主要是清除了和中的關(guān)鍵參數(shù),比如時(shí)設(shè)置的以及等,清除后又調(diào)用了,根據(jù)之前的邏輯,當(dāng)然不可能重載成功,因?yàn)橐呀?jīng)為了,執(zhí)行到就已經(jīng)結(jié)束了,其實(shí)算是這個(gè)模塊中很關(guān)鍵的一個(gè)函數(shù),這個(gè)類也是這個(gè)模塊的核心所在,以后有時(shí)間繼續(xù)研究。

今天看書遇到了flask login模塊中的信號(hào)機(jī)制,看到user_loader這個(gè)裝飾器時(shí)有些疑惑,為什么需要這個(gè)裝飾器呢,先看一下源碼:

def user_loader(self, callback):
    """
    This sets the callback for reloading a user from the session. The
    function you set should take a user ID (a ``unicode``) and return a
    user object, or ``None`` if the user does not exist.

    :param callback: The callback for retrieving a user object.
    :type callback: callable
    """
    self.user_callback = callback
    return callback

看到這不禁疑惑,它的作用只是將被它包裝的函數(shù)存到self.user_callback這個(gè)屬性中去,我們先到login_user這個(gè)登陸函數(shù)中去看看:

def login_user(user, remember=False, duration=None, force=False, fresh=True):
    if not force and not user.is_active:
        return False

    user_id = getattr(user, current_app.login_manager.id_attribute)()
    session["user_id"] = user_id
    session["_fresh"] = fresh
    session["_id"] = current_app.login_manager._session_identifier_generator()

    if remember:
        session["remember"] = "set"
        if duration is not None:
            try:
                # equal to timedelta.total_seconds() but works with Python 2.6
                session["remember_seconds"] = (duration.microseconds +
                                               (duration.seconds +
                                                duration.days * 24 * 3600) *
                                               10**6) / 10.0**6
            except AttributeError:
                raise Exception("duration must be a datetime.timedelta, "
                                "instead got: {0}".format(duration))

    _request_ctx_stack.top.user = user
    user_logged_in.send(current_app._get_current_object(), user=_get_user())
    return True

可以看到,login_user這個(gè)函數(shù)接受user這個(gè)主要的參數(shù),getattr(user, current_app.login_manager.id_attribute)()這句是為了調(diào)用user中的get_id方法

self.id_attribute = ID_ATTRIBUTE
ID_ATTRIBUTE = "get_id"

注意在getattr后面還有個(gè)()所以會(huì)調(diào)用對(duì)應(yīng)的方法,所以u(píng)ser_id中就存放了登陸用戶的id號(hào),并寫入到session中去,如果設(shè)置了remember為True的話,關(guān)掉瀏覽器重新打開后,用戶不會(huì)退出,函數(shù)的最后_request_ctx_stack.top.user = user,將當(dāng)前user加入到請(qǐng)求上下文的棧頂,就能用current_user獲取了。
上面說(shuō)到self.user_callback已經(jīng)存了被user_loader裝飾的函數(shù),那么在哪里用到了它呢,我在login_manager.py中查找,發(fā)現(xiàn)只有一個(gè)方法使用到了這個(gè)熟悉,這個(gè)方法是reload_user():

def reload_user(self, user=None):
    """
    This set the ctx.user with the user object loaded by your customized
    user_loader callback function, which should retrieved the user object
    with the user_id got from session.

    Syntax example:
    from flask_login import LoginManager
    @login_manager.user_loader
    def any_valid_func_name(user_id):
        # get your user object using the given user_id,
        # if you use SQLAlchemy, for example:
        user_obj = User.query.get(int(user_id))
        return user_obj

    Reason to let YOU define this self.user_callback:
        Because we won"t know how/where you will load you user object.
    """
    ctx = _request_ctx_stack.top

    if user is None:
        user_id = session.get("user_id")
        if user_id is None:
            ctx.user = self.anonymous_user()
        else:
            if self.user_callback is None:
                raise Exception(
                    "No user_loader has been installed for this "
                    "LoginManager. Refer to"
                    "https://flask-login.readthedocs.io/"
                    "en/latest/#how-it-works for more info.")
            user = self.user_callback(user_id)
            if user is None:
                ctx.user = self.anonymous_user()
            else:
                ctx.user = user
    else:
        ctx.user = user

它先從請(qǐng)求上下文中取出最新的請(qǐng)求,如果沒有傳入user,那么會(huì)從session中試圖取出對(duì)應(yīng)的user_id,這是一種保護(hù)機(jī)制,不使用cookie,而使用session,user_id在login時(shí)會(huì)寫入session,如果登陸時(shí)remember參數(shù)傳入了True,那么關(guān)閉瀏覽器重新打開后session["user_id"]將不會(huì)被清除,這時(shí)候也就可以獲取到了,如果登陸時(shí)沒有設(shè)置remember為True,那么關(guān)閉瀏覽器后user_id會(huì)被設(shè)為None,則ctx.user = self.anonymous_user(),棧頂?shù)挠脩魹槟涿脩簦簿托枰匦碌顷懥?取出了user_id,并且self.user_callback不為空,則會(huì)調(diào)用被user_loader裝飾的函數(shù),并傳入user_id,在被裝飾的函數(shù)中我們要根據(jù)這個(gè)user_id來(lái)查找并返回對(duì)應(yīng)的用戶實(shí)例,如果成功返回,那么當(dāng)前請(qǐng)求上下文棧頂?shù)挠脩艟驮O(shè)置為返回的用戶。
你可能會(huì)問(wèn),為什么要重載用戶呢?因?yàn)閔ttp協(xié)議是無(wú)狀態(tài)的,每次都會(huì)發(fā)送一個(gè)新的請(qǐng)求,請(qǐng)求上下文的棧頂會(huì)被新的請(qǐng)求覆蓋,對(duì)應(yīng)的user屬性也就沒了,所以需要通過(guò)reload_user重載上一次記錄在session中并且未被清除的用戶,重載失敗則需要重新登陸,這也就是這個(gè)裝飾器的作用了。
最后我們看下logout_user()這個(gè)方法:

def logout_user():

"""
Logs a user out. (You do not need to pass the actual user.) This will
also clean up the remember me cookie if it exists.
"""

user = _get_user()

if "user_id" in session:
    session.pop("user_id")

if "_fresh" in session:
    session.pop("_fresh")

cookie_name = current_app.config.get("REMEMBER_COOKIE_NAME", COOKIE_NAME)
if cookie_name in request.cookies:
    session["remember"] = "clear"
    if "remember_seconds" in session:
        session.pop("remember_seconds")

user_logged_out.send(current_app._get_current_object(), user=user)

current_app.login_manager.reload_user()
return True

logout主要是清除了session和cookie中的關(guān)鍵參數(shù),比如login時(shí)設(shè)置的user_id以及remember等,清除后又調(diào)用了reload_user(),根據(jù)之前的邏輯,當(dāng)然不可能重載成功,因?yàn)閡ser_id已經(jīng)為None了,執(zhí)行到ctx.user = self.anonymous_user()就已經(jīng)結(jié)束了,其實(shí)reload_user算是這個(gè)模塊中很關(guān)鍵的一個(gè)函數(shù),login_manager這個(gè)類也是這個(gè)模塊的核心所在,以后有時(shí)間繼續(xù)研究。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/44733.html

相關(guān)文章

  • 基于 oracle flask 項(xiàng)目(二)——用戶登錄

    摘要:自行定義的方法用于權(quán)限判斷繼承至該類的用戶模型將作為未登陸時(shí)的用戶模型可以保持代碼的一致性。但是這樣的方法很危險(xiǎn),很造成一些其它項(xiàng)目的兼容性問(wèn)題。打開頁(yè)面,顯示正常。 flask 相對(duì)于很多國(guó)企的 oracle 數(shù)據(jù)庫(kù)而言,是比較新的,因此很多古老的設(shè)計(jì)并不一定適合較新的 flask 的標(biāo)準(zhǔn),但作為后來(lái)者,你得向前兼容,你得適應(yīng)需求。本章內(nèi)容就來(lái)解釋一下上一章——基于 oracle 的...

    chunquedong 評(píng)論0 收藏0
  • 用Python+Flask實(shí)戰(zhàn)一個(gè)實(shí)用留言板Demo

    摘要:混雜著工作室圖片網(wǎng)任務(wù)截至今天終于完成了暑假另一個(gè)任務(wù)把考核任務(wù)按照狗書再寫一遍受益匪淺,路途荊棘叢生。。。。 混雜著工作室圖片網(wǎng)任務(wù),截至今天終于完成了暑假另一個(gè)任務(wù)把考核任務(wù)按照狗書再寫一遍受益匪淺,路途荊棘叢生。。。。這里主要記錄了增加的功能,更多的可以看源代碼代碼在線預(yù)覽 上傳頭像404 Flask上傳文件我實(shí)現(xiàn)的主要思路就是,上傳文件到服務(wù)器,然后讀取文件當(dāng)然你可以用二進(jìn)制...

    klinson 評(píng)論0 收藏0
  • 從app.route裝飾引發(fā)對(duì)endpoint思考

    摘要:為字段賦值,返回給客戶端進(jìn)行重定向總結(jié)一個(gè)視圖函數(shù)的如果不設(shè)置那么就是視圖函數(shù)名。為和搭起橋梁,使得整個(gè)后端框架更加靈活。返回的是視圖函數(shù)對(duì)應(yīng)的,是對(duì)應(yīng)視圖函數(shù)裝飾器傳入的值。 還是先來(lái)看看源碼 def route(self, rule, **options): A decorator that is used to register a view function for a...

    妤鋒シ 評(píng)論0 收藏0
  • 「mixin模式」與「裝飾模式」

    摘要:今天看到的提問(wèn)關(guān)于裝飾模式引發(fā)的思考又想起了。其實(shí),模式就是裝飾器模式。這就造成了和裝飾器模式的一個(gè)本質(zhì)不同基于類,還是基于對(duì)象。 今天看到 @chengxuyuan_329633 的提問(wèn) 關(guān)于裝飾模式引發(fā)的思考 又想起了 mixin。mixin 模式和裝飾器模式很相似。 其實(shí),mixin模式就是裝飾器模式。 那么單利模式呢?呵呵,其實(shí)就是全局變量/對(duì)象。 當(dāng)過(guò)程式開發(fā)變得越來(lái)越...

    陸斌 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<