Django:中間件

中間件

中間件介紹

什么是中間件

官方的說法是:中間件是一個(gè)用來處理Django的請(qǐng)求和相應(yīng)的框架級(jí)別的鉤子。他是以個(gè)輕量滞造、低級(jí)別的插件系統(tǒng),用于在全局范圍內(nèi)改變Django和輸入和輸出栋烤。每個(gè)中間件組件都負(fù)責(zé)做一些特定的功能谒养。

但是由于其影響的是全局,所以要謹(jǐn)慎使用,使用不當(dāng)會(huì)影響性能买窟。

說的直白一些中間件就是幫助我們?cè)谝晥D函數(shù)執(zhí)行之前和執(zhí)行之后都可以做一些額外的操作丰泊,它本質(zhì)上就是一個(gè)自定義類,類中定義了幾個(gè)方法始绍,Django框架會(huì)在請(qǐng)求的特定時(shí)間去執(zhí)行這些方法瞳购。

我們一直都在使用中間件,只是沒有注意過罷了亏推。打開Django項(xiàng)目的settings.py文件学赛,可看到下面的MIDDLEWARE配置項(xiàng)。

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

MIDDLEWARE配置項(xiàng)是一個(gè)列表吞杭,列表中是一個(gè)個(gè)字符串盏浇,這些字符串其實(shí)是一個(gè)個(gè)類,也就是一個(gè)個(gè)中間件芽狗。

我們之前已經(jīng)接觸過一個(gè)csrf相關(guān)的中間件了绢掰?我們一開始讓大家把他注釋掉,再提交post請(qǐng)求的時(shí)候童擎,就不會(huì)被forbidden了滴劲,后來學(xué)會(huì)使用csrf_token之后就不再注釋這個(gè)中間件了。

那接下來就學(xué)習(xí)中間件中的方法以及這些方法什么時(shí)候被執(zhí)行顾复。

自定義中間件

中間件可以定義五個(gè)方法哑芹,分別是:

  • process_request(self, request)
  • process_view(self, request, view_func, view_args, view_kwargs)
  • process_template_response(self, request, response)
  • process_exception(self, request, exception)
  • process_response(self, request, response)

以上方法d的返回值可以使None回一個(gè)HttpResponse對(duì)象, 如果是None捕透, 則繼續(xù)安好django定義的規(guī)則向后繼續(xù)執(zhí)行聪姿,如果是HttpResponse對(duì)象,則直接將該對(duì)象返回給用戶乙嘀。

自定義一個(gè)中間件

from django.utils.deprecation import MiddlewareMixin


class MD1(MiddlewareMixin):

    def process_request(self, request):
        print("MD1里面的 process_request")

    def process_response(self, request, response):
        print("MD1里面的 process_response")
        return response

process_request

process_request有一個(gè)參數(shù)末购,就是request,這個(gè)request和視圖函數(shù)中的request是一樣的虎谢。

它的返回值可以是None也可以是HttpResponse對(duì)象盟榴。返回值是None的話,按正常流程繼續(xù)走婴噩,交給下一個(gè)中間件處理擎场,如果是HttpResponse對(duì)象,Django將不執(zhí)行視圖函數(shù)几莽,而將相應(yīng)對(duì)象返回給瀏覽器迅办。

我們來看看多個(gè)中間件時(shí),Django是如何執(zhí)行其中的process_request方法的章蚣。

from django.utils.deprecation import MiddlewareMixin


class MD1(MiddlewareMixin):

    def process_request(self, request):
        print("MD1里面的 process_request")


class MD2(MiddlewareMixin):
    def process_request(self, request):
        print("MD2里面的 process_request")
        pass

在settings.py的MIDDLEWARE配置項(xiàng)中注冊(cè)上述兩個(gè)自定義中間件:

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'middlewares.MD1',  # 自定義中間件MD1
    'middlewares.MD2'  # 自定義中間件MD2
]

此時(shí)我們?cè)L問一個(gè)視圖站欺,會(huì)發(fā)現(xiàn)終端打印出以下內(nèi)容:

MD1里面的 process_request
MD2里面的 process_request
app01 中的 index視圖

把MD1和MD2的位置調(diào)換一下,再訪問一個(gè)視圖,會(huì)發(fā)現(xiàn)終端打印的內(nèi)容如下:

MD2里面的 process_request
MD1里面的 process_request
app01 中的 index視圖

看結(jié)果我們知道:是凸函數(shù)還是最后追星的矾策,MD2比MD1限制性自己的process_request方法磷账。

再打印一下兩個(gè)自定義中間件中process_request方法中的request參數(shù),會(huì)發(fā)現(xiàn)他們是同一個(gè)對(duì)象贾虽。

總結(jié):
1逃糟、中間件的process_request方法是在執(zhí)行是凸函數(shù)之前執(zhí)行的。
2蓬豁、當(dāng)配置多個(gè)中間件時(shí)绰咽,會(huì)按照MIDDLEWARE中的注冊(cè)順序,也就是列表的索引值庆尘,從前往后依次執(zhí)行的剃诅。
3、不同中間件之間傳遞的request都是同一個(gè)對(duì)象

多個(gè)中間件中的process_response方法是按照MIDDLEWARE中的注冊(cè)順序的倒序執(zhí)行的驶忌,也就是說第一個(gè)中間件的process_request方法先執(zhí)行而它的process_response方法最后執(zhí)行矛辕。

process_response

他有兩個(gè)參數(shù),一個(gè)是request付魔,一個(gè)是response聊品,request就是上述例子中一樣的對(duì)象,response是視圖函數(shù)返回的HttpResponse對(duì)象几苍。該方法的返回值也必須是HttpResponse對(duì)象翻屈。

給上述的M1和M2加上process_response方法:

from django.utils.deprecation import MiddlewareMixin


class MD1(MiddlewareMixin):

    def process_request(self, request):
        print("MD1里面的 process_request")

    def process_response(self, request, response):
        print("MD1里面的 process_response")
        return response


class MD2(MiddlewareMixin):
    def process_request(self, request):
        print("MD2里面的 process_request")
        pass

    def process_response(self, request, response):
        print("MD2里面的 process_response")
        return response

訪問一下視圖,看一下終端的輸出:

MD2里面的 process_request
MD1里面的 process_request
app01 中的 index視圖
MD1里面的 process_response
MD2里面的 process_response

多個(gè)中間件中的process_response方法是按照MIDDLEWARE中的注冊(cè)順序倒序執(zhí)行的妻坝,也就是說第一個(gè)中間件的process_request方法首先執(zhí)行伸眶,而它的process_response方法最后執(zhí)行,最后一個(gè)中間件的process_request方法最后一個(gè)執(zhí)行刽宪,它的process_response方法是最先執(zhí)行厘贼。

process_view

process_view(self, request, view_func, view_args, view_kwargs)

該方法有四個(gè)參數(shù)

request是HttpRequest對(duì)象。

view_func是Django即將使用的視圖函數(shù)圣拄。 (它是實(shí)際的函數(shù)對(duì)象嘴秸,而不是函數(shù)的名稱作為字符串。)

view_args是將傳遞給視圖的位置參數(shù)的列表.

view_kwargs是將傳遞給視圖的關(guān)鍵字參數(shù)的字典庇谆。 view_args和view_kwargs都不包含第一個(gè)視圖參數(shù)(request)岳掐。

Django會(huì)在調(diào)用視圖函數(shù)之前調(diào)用process_view方法。

它應(yīng)該返回None或一個(gè)HttpResponse對(duì)象饭耳。 如果返回None串述,Django將繼續(xù)處理這個(gè)請(qǐng)求,執(zhí)行任何其他中間件的process_view方法哥攘,然后在執(zhí)行相應(yīng)的視圖剖煌。 如果它返回一個(gè)HttpResponse對(duì)象材鹦,Django不會(huì)調(diào)用適當(dāng)?shù)囊晥D函數(shù)逝淹。 它將執(zhí)行中間件的process_response方法并將應(yīng)用到該HttpResponse并返回結(jié)果耕姊。

給MD1和MD2添加process_view方法:

from django.utils.deprecation import MiddlewareMixin


class MD1(MiddlewareMixin):

    def process_request(self, request):
        print("MD1里面的 process_request")

    def process_response(self, request, response):
        print("MD1里面的 process_response")
        return response

    def process_view(self, request, view_func, view_args, view_kwargs):
        print("-" * 80)
        print("MD1 中的process_view")
        print(view_func, view_func.__name__)


class MD2(MiddlewareMixin):
    def process_request(self, request):
        print("MD2里面的 process_request")
        pass

    def process_response(self, request, response):
        print("MD2里面的 process_response")
        return response

    def process_view(self, request, view_func, view_args, view_kwargs):
        print("-" * 80)
        print("MD2 中的process_view")
        print(view_func, view_func.__name__)

訪問index視圖函數(shù),看一下輸出結(jié)果:

MD2里面的 process_request
MD1里面的 process_request


MD2 中的process_view
<function index at 0x000001DE68317488> index


MD1 中的process_view
<function index at 0x000001DE68317488> index
app01 中的 index視圖
MD1里面的 process_response
MD2里面的 process_response

process_view方法是在process_request之后栅葡,視圖函數(shù)之前執(zhí)行的茉兰,執(zhí)行順序按照MIDDLEWARE中的注冊(cè)順序從前到后順序執(zhí)行的

process_exception

process_exception(self, request, exception)

該方法兩個(gè)參數(shù):

一個(gè)HttpRequest對(duì)象

一個(gè)exception是視圖函數(shù)異常產(chǎn)生的Exception對(duì)象。

這個(gè)方法只有在視圖函數(shù)中出現(xiàn)異常了才執(zhí)行欣簇,它返回的值可以是一個(gè)None也可以是一個(gè)HttpResponse對(duì)象规脸。如果是HttpResponse對(duì)象,Django將調(diào)用模板和中間件中的process_response方法熊咽,并返回給瀏覽器莫鸭,否則將默認(rèn)處理異常。如果返回一個(gè)None横殴,則交給下一個(gè)中間件的process_exception方法來處理異常被因。它的執(zhí)行順序也是按照中間件注冊(cè)順序的倒序執(zhí)行。

給MD1和MD2添加上這個(gè)方法:

from django.utils.deprecation import MiddlewareMixin


class MD1(MiddlewareMixin):

    def process_request(self, request):
        print("MD1里面的 process_request")

    def process_response(self, request, response):
        print("MD1里面的 process_response")
        return response

    def process_view(self, request, view_func, view_args, view_kwargs):
        print("-" * 80)
        print("MD1 中的process_view")
        print(view_func, view_func.__name__)

    def process_exception(self, request, exception):
        print(exception)
        print("MD1 中的process_exception")


class MD2(MiddlewareMixin):
    def process_request(self, request):
        print("MD2里面的 process_request")
        pass

    def process_response(self, request, response):
        print("MD2里面的 process_response")
        return response

    def process_view(self, request, view_func, view_args, view_kwargs):
        print("-" * 80)
        print("MD2 中的process_view")
        print(view_func, view_func.__name__)

    def process_exception(self, request, exception):
        print(exception)
        print("MD2 中的process_exception")

如果視圖函數(shù)中無異常衫仑,process_exception方法不執(zhí)行梨与。

想辦法,在視圖函數(shù)中拋出一個(gè)異常:

def index(request):
    print("app01 中的 index視圖")
    raise ValueError("呵呵")
    return HttpResponse("O98K")

在MD1的process_exception中返回一個(gè)響應(yīng)對(duì)象:


class MD1(MiddlewareMixin):

    def process_request(self, request):
        print("MD1里面的 process_request")

    def process_response(self, request, response):
        print("MD1里面的 process_response")
        return response

    def process_view(self, request, view_func, view_args, view_kwargs):
        print("-" * 80)
        print("MD1 中的process_view")
        print(view_func, view_func.__name__)

    def process_exception(self, request, exception):
        print(exception)
        print("MD1 中的process_exception")
        return HttpResponse(str(exception))  # 返回一個(gè)響應(yīng)對(duì)象

看輸出結(jié)果:

MD2里面的 process_request
MD1里面的 process_request


MD2 中的process_view
<function index at 0x0000022C09727488> index


MD1 中的process_view
<function index at 0x0000022C09727488> index
app01 中的 index視圖
呵呵
MD1 中的process_exception
MD1里面的 process_response
MD2里面的 process_response

注意文狱,這里并沒有執(zhí)行MD2的process_exception方法粥鞋,因?yàn)镸D1中的process_exception方法直接返回了一個(gè)響應(yīng)對(duì)象

process_template_response

process_template_response(self, request, response)

它的參數(shù),一個(gè)HttpRequest對(duì)象瞄崇,response是TemplateResponse對(duì)象(由視圖函數(shù)或者中間件產(chǎn)生)呻粹。

process_template_response是在視圖函數(shù)執(zhí)行完成后立即執(zhí)行,但是它有一個(gè)前提條件苏研,那就是視圖函數(shù)返回的對(duì)象有一個(gè)render()方法(或者表明該對(duì)象是一個(gè)TemplateResponse對(duì)象或等價(jià)方法)等浊。

class MD1(MiddlewareMixin):

    def process_request(self, request):
        print("MD1里面的 process_request")

    def process_response(self, request, response):
        print("MD1里面的 process_response")
        return response

    def process_view(self, request, view_func, view_args, view_kwargs):
        print("-" * 80)
        print("MD1 中的process_view")
        print(view_func, view_func.__name__)

    def process_exception(self, request, exception):
        print(exception)
        print("MD1 中的process_exception")
        return HttpResponse(str(exception))

    def process_template_response(self, request, response):
        print("MD1 中的process_template_response")
        return response


class MD2(MiddlewareMixin):
    def process_request(self, request):
        print("MD2里面的 process_request")
        pass

    def process_response(self, request, response):
        print("MD2里面的 process_response")
        return response

    def process_view(self, request, view_func, view_args, view_kwargs):
        print("-" * 80)
        print("MD2 中的process_view")
        print(view_func, view_func.__name__)

    def process_exception(self, request, exception):
        print(exception)
        print("MD2 中的process_exception")

    def process_template_response(self, request, response):
        print("MD2 中的process_template_response")
        return response

views.py

def index(request):
    print("app01 中的 index視圖")

    def render():
        print("in index/render")
        return HttpResponse("O98K")
    rep = HttpResponse("OK")
    rep.render = render
    return rep

訪問index視圖,終端輸出結(jié)果:

MD2里面的 process_request
MD1里面的 process_request


MD2 中的process_view
<function index at 0x000001C111B97488> index


MD1 中的process_view
<function index at 0x000001C111B97488> index
app01 中的 index視圖
MD1 中的process_template_response
MD2 中的process_template_response
in index/render
MD1里面的 process_response
MD2里面的 process_response

從結(jié)果看出:

視圖函數(shù)執(zhí)行完之后楣富,立即執(zhí)行了中間件的process_template_response方法凿掂,順序是倒序,先執(zhí)行MD1的纹蝴,在執(zhí)行MD2的庄萎,接著執(zhí)行了視圖函數(shù)返回的HttpResponse對(duì)象的render方法,返回了一個(gè)新的HttpResponse對(duì)象塘安,接著執(zhí)行中間件的process_response方法糠涛。

中間件的執(zhí)行流程

請(qǐng)求到達(dá)中間件之后,先按照正序執(zhí)行每個(gè)注冊(cè)中間件的process_reques方法兼犯,process_request方法返回的值是None忍捡,就依次執(zhí)行集漾,如果返回的值是HttpResponse對(duì)象,不再執(zhí)行后面的process_request方法砸脊,而是執(zhí)行當(dāng)前對(duì)應(yīng)中間件的process_response方法具篇,將HttpResponse對(duì)象返回給瀏覽器。也就是說:如果MIDDLEWARE中注冊(cè)了6個(gè)中間件凌埂,執(zhí)行過程中驱显,第3個(gè)中間件返回了一個(gè)HttpResponse對(duì)象,那么第4,5,6中間件的process_request和process_response方法都不執(zhí)行瞳抓,順序執(zhí)行3,2,1中間件的process_response方法埃疫。


2.png

process_request方法都執(zhí)行完后,匹配路由孩哑,找到要執(zhí)行的視圖函數(shù)栓霜,先不執(zhí)行視圖函數(shù),先執(zhí)行中間件中的process_view方法横蜒,process_view方法返回None胳蛮,繼續(xù)按順序執(zhí)行,所有process_view方法執(zhí)行完后執(zhí)行視圖函數(shù)愁铺。加入中間件3 的process_view方法返回了HttpResponse對(duì)象鹰霍,則4,5,6的process_view以及視圖函數(shù)都不執(zhí)行,直接從最后一個(gè)中間件茵乱,也就是中間件6的process_response方法開始倒序執(zhí)行茂洒。


3.png

process_template_response和process_exception兩個(gè)方法的觸發(fā)是有條件的,執(zhí)行順序也是倒序瓶竭《缴祝總結(jié)所有的執(zhí)行流程如下:

4.png
5.png

中間件版登錄驗(yàn)證

中間件版的登錄驗(yàn)證需要依靠session,所以數(shù)據(jù)庫(kù)中要有django_session表斤贰。

urls.py

from django.conf.urls import url
from app01 import views

urlpatterns = [
    url(r'^index/$', views.index),
    url(r'^login/$', views.login, name='login'),
]

views.py

from django.shortcuts import render, HttpResponse, redirect


def index(request):
    return HttpResponse('this is index')


def home(request):
    return HttpResponse('this is home')


def login(request):
    if request.method == "POST":
        user = request.POST.get("user")
        pwd = request.POST.get("pwd")

        if user == "Q1mi" and pwd == "123456":
            # 設(shè)置session
            request.session["user"] = user
            # 獲取跳到登陸頁(yè)面之前的URL
            next_url = request.GET.get("next")
            # 如果有智哀,就跳轉(zhuǎn)回登陸之前的URL
            if next_url:
                return redirect(next_url)
            # 否則默認(rèn)跳轉(zhuǎn)到index頁(yè)面
            else:
                return redirect("/index/")
    return render(request, "login.html")

login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="x-ua-compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>登錄頁(yè)面</title>
</head>
<body>
<form action="{% url 'login' %}">
    <p>
        <label for="user">用戶名:</label>
        <input type="text" name="user" id="user">
    </p>
    <p>
        <label for="pwd">密 碼:</label>
        <input type="text" name="pwd" id="pwd">
    </p>
    <input type="submit" value="登錄">
</form>
</body>
</html>

middlewares.py

class AuthMD(MiddlewareMixin):
    white_list = ['/login/', ]  # 白名單
    balck_list = ['/black/', ]  # 黑名單

    def process_request(self, request):
        from django.shortcuts import redirect, HttpResponse

        next_url = request.path_info
        print(request.path_info, request.get_full_path())

        if next_url in self.white_list or request.session.get("user"):
            return
        elif next_url in self.balck_list:
            return HttpResponse('This is an illegal URL')
        else:
            return redirect("/login/?next={}".format(next_url))

在settings.py中注冊(cè)

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'middlewares.AuthMD',
]

AuthMD中間件注冊(cè)后,所有的請(qǐng)求都要走AuthMD的process_request方法荧恍。

訪問的URL在白名單內(nèi)或者session中有user用戶名瓷叫,則不做阻攔走正常流程;

如果URL在黑名單中送巡,則返回This is an illegal URL的字符串摹菠;

正常的URL但是需要登錄后訪問,讓瀏覽器跳轉(zhuǎn)到登錄頁(yè)面骗爆。

注:AuthMD中間件中需要session次氨,所以AuthMD注冊(cè)的位置要在session中間的下方。

附加:Django請(qǐng)求流程圖


6.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末摘投,一起剝皮案震驚了整個(gè)濱河市煮寡,隨后出現(xiàn)的幾起案子虹蓄,更是在濱河造成了極大的恐慌,老刑警劉巖幸撕,帶你破解...
    沈念sama閱讀 212,884評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件薇组,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡杈帐,警方通過查閱死者的電腦和手機(jī)体箕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,755評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門专钉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來挑童,“玉大人,你說我怎么就攤上這事跃须≌镜穑” “怎么了?”我有些...
    開封第一講書人閱讀 158,369評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵菇民,是天一觀的道長(zhǎng)尽楔。 經(jīng)常有香客問我,道長(zhǎng)第练,這世上最難降的妖魔是什么阔馋? 我笑而不...
    開封第一講書人閱讀 56,799評(píng)論 1 285
  • 正文 為了忘掉前任,我火速辦了婚禮娇掏,結(jié)果婚禮上呕寝,老公的妹妹穿的比我還像新娘。我一直安慰自己婴梧,他們只是感情好下梢,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,910評(píng)論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著塞蹭,像睡著了一般孽江。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上番电,一...
    開封第一講書人閱讀 50,096評(píng)論 1 291
  • 那天岗屏,我揣著相機(jī)與錄音,去河邊找鬼漱办。 笑死这刷,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的洼冻。 我是一名探鬼主播崭歧,決...
    沈念sama閱讀 39,159評(píng)論 3 411
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼撞牢!你這毒婦竟也來了率碾?” 一聲冷哼從身側(cè)響起叔营,我...
    開封第一講書人閱讀 37,917評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎所宰,沒想到半個(gè)月后绒尊,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,360評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡仔粥,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,673評(píng)論 2 327
  • 正文 我和宋清朗相戀三年婴谱,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片躯泰。...
    茶點(diǎn)故事閱讀 38,814評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡谭羔,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出麦向,到底是詐尸還是另有隱情瘟裸,我是刑警寧澤,帶...
    沈念sama閱讀 34,509評(píng)論 4 334
  • 正文 年R本政府宣布诵竭,位于F島的核電站话告,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏卵慰。R本人自食惡果不足惜沙郭,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,156評(píng)論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望裳朋。 院中可真熱鬧病线,春花似錦、人聲如沸再扭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)泛范。三九已至让虐,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間罢荡,已是汗流浹背赡突。 一陣腳步聲響...
    開封第一講書人閱讀 32,123評(píng)論 1 267
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留区赵,地道東北人惭缰。 一個(gè)月前我還...
    沈念sama閱讀 46,641評(píng)論 2 362
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像笼才,于是被迫代替她去往敵國(guó)和親漱受。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,728評(píng)論 2 351

推薦閱讀更多精彩內(nèi)容