基于Django實(shí)現(xiàn) RESTful API 之RestFramework框架3

接下來學(xué)習(xí)RestFramework框架中的認(rèn)證芽狗、權(quán)限隘膘、頻率組件的使用

一旗芬、首先實(shí)現(xiàn)用戶login登錄認(rèn)證功能

做用戶登錄認(rèn)證功能可以通過session纳击、cookie和token三種形式,下面的login認(rèn)證基于token實(shí)現(xiàn)

  • 關(guān)鍵點(diǎn)
    -- 首先需要設(shè)計(jì)用戶表昧识、用戶token表钠四,用戶表需要包含用戶類型,用戶token表包含用戶的token值
    -- 用戶的token值應(yīng)該是一個(gè)隨機(jī)的跪楞、動(dòng)態(tài)的字符串
    -- 用戶認(rèn)證成功需要將用戶信息和對(duì)應(yīng)的token值返回缀去,后續(xù)訪問url就可以通過token值來判斷用戶的狀態(tài)

附:models.py

from django.db import models

class Userinfo(models.Model):
    name = models.CharField(max_length=32)
    pwd = models.CharField(max_length=64)
    user_type = models.IntegerField(choices=((1,"common_user"),(2,"VIP_user"),(3,"SVIP_user")))

class UserToken(models.Model):
    user = models.OneToOneField(to="Userinfo")
    token = models.CharField(max_length=128)
  • view.py認(rèn)證邏輯
from rest_framework.views import APIView
from rest_framework.response import Response
import uuid


class LoginView(APIView):
    """
    1000:成功
    1001:用戶名或者密碼錯(cuò)誤
    1002:異常錯(cuò)誤
    """
    def post(self, request):
        #自定義的返回體數(shù)據(jù)
        ret = {"code": 1000, "msg": None, "user": None}
        try:
            print(request.data)  # 重裝后的request侣灶,request.data從中取所需的數(shù)據(jù)
            name = request.data.get("name")#獲取前端用戶名
            pwd = request.data.get("pwd")#獲取前端密碼
            #數(shù)據(jù)庫校驗(yàn)用戶名密碼是否正確
            user_obj = models.Userinfo.objects.filter(name=name, pwd=pwd).first()
            if user_obj:
                #通過uuid模塊獲得隨機(jī)字符串作為token值
                random_str = uuid.uuid4()
                #UserToken表中有該用戶的信息就用新token值覆蓋,沒有就創(chuàng)建數(shù)據(jù)
                models.UserToken.objects.update_or_create(user=user_obj, defaults={"token": random_str})
                ret["user"] = user_obj.name
                ret["token"] = random_str
            else:
                ret["code"] = 1001
                ret["msg"] = "用戶名或者密碼錯(cuò)誤"

        except Exception as e:
            ret["code"] = 1002
            ret["msg"] = str(e)

        return Response(ret)
這樣就實(shí)現(xiàn)了用戶的login認(rèn)證缕碎。褥影。。咏雌。凡怎。。赊抖。栅贴。。

二熏迹、基于RestFramework的認(rèn)證組件做視圖處理類的user認(rèn)證

首先看一下UserAuth的具體用法:

  • 關(guān)鍵點(diǎn):
    --視圖處理類下定義名為authentication_classes屬性,屬性值是一個(gè)列表或者元組
    --寫一個(gè)UserAuth(類名隨便)認(rèn)證的類凝赛,將類名添加到authentication_classes列表中
    --UserAuth認(rèn)證類必須有一個(gè)authenticate(self,request)方法,這個(gè)方法下寫用戶認(rèn)證邏輯注暗,認(rèn)證成功:可以返回?cái)?shù)據(jù),也可以什么都不做墓猎。認(rèn)證失敗:捆昏,必須拋異常
    -- UserAuth類繼承BaseAuthentication類,其實(shí)就是給類加了一個(gè)authenticate_header方法毙沾,沒理由骗卜,源碼要求!

這四點(diǎn)你一定看不懂是什么意思左胞,很正常寇仓,這都是RestFramework源碼給設(shè)定的特定規(guī)則,稍后認(rèn)證源碼流程分析會(huì)一一分析解答

view.py代碼示例:代碼實(shí)現(xiàn)了book視圖類的用戶認(rèn)證功能

from rest_framework.exceptions import AuthenticationFailed
from rest_framework.authentication import BaseAuthentication

#用于認(rèn)證的類
class UserAuth(BaseAuthentication):
   def authenticate(self, request):
       token = request.query_params.get("token")
       usertoken_obj = models.UserToken.objects.filter(token=token).first()
       if usertoken_obj:
           return usertoken_obj.user, usertoken_obj.token
       else:
           raise AuthenticationFailed("用戶認(rèn)證失敗烤宙,您無權(quán)訪問1榉场!躺枕!")

# book視圖處理類
class Booklist(ModelViewSet):
   authentication_classes = [UserAuth, ]

   queryset = models.Book.objects.all()
   serializer_class = BooklistSerializer

接下來一張圖帶你透析認(rèn)證組件:

UserAuth認(rèn)證源碼解析.jpg

- 這樣的寫法只是給book視圖類加上了認(rèn)證服猪,可以將認(rèn)證類單獨(dú)卸載一個(gè)py文件中,然后在全局settings中添加對(duì)應(yīng)的配置項(xiàng)拐云,這樣就可以做到對(duì)所有的視圖類添加認(rèn)證功能了0罩怼!叉瘩!

根據(jù)實(shí)際需求選擇合適的方法I排痢!房揭!

app001-utils-Userauth.py

from app001 import models
from rest_framework.exceptions import AuthenticationFailed
from rest_framework.authentication import BaseAuthentication

class UserAuth(BaseAuthentication):
    def authenticate(self, request):
        token = request.query_params.get("token")
        usertoken_obj = models.UserToken.objects.filter(token=token).first()
        if usertoken_obj:
            return usertoken_obj.user, usertoken_obj.token
        else:
            raise AuthenticationFailed("用戶認(rèn)證失敗备闲,您無權(quán)訪問I味恕!恬砂!")

settings.py

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'app001.utils.Userauth.UserAuth',
    )
}

view.py

from app001 import models
from app001.serializers.bookserializer import BooklistSerializer

# 重裝了APIView
from rest_framework.viewsets import ModelViewSet

# book視圖處理類
class Booklist(ModelViewSet):
   queryset = models.Book.objects.all()
   serializer_class = BooklistSerializer

三咧纠、基于RestFramework的認(rèn)證組件做視圖處理類的權(quán)限認(rèn)證

首先看一下UserAuth的具體用法:

  • 關(guān)鍵點(diǎn):
    --視圖處理類下定義名為permission_classes屬性,屬性值是一個(gè)列表或者元組
    --寫一個(gè)UserAuth(類名隨便)認(rèn)證的類泻骤,將類名添加到permission_classes列表中
    --UserAuth認(rèn)證類必須有一個(gè)has_permission(self,request,view)方法,這個(gè)方法下寫用戶認(rèn)證邏輯漆羔,認(rèn)證成功:返回true。認(rèn)證失敗:狱掂,返回false演痒。

permission源碼執(zhí)行流程:

permission源碼解析_副本.jpg

  • app001-utils-permission_class.py
from rest_framework.permissions import BasePermission
class SVIPPermission(BasePermission):
    message="您沒有訪問權(quán)限!"
    def has_permission(self,request,view):
        if request.user.user_type >= 2:
            return True
        return False
  • view.py
from app001 import models
from app001.serializers.bookserializer import BooklistSerializer
# 重裝了APIView
from rest_framework.viewsets import ModelViewSet

from app001.utils.permission_class import SVIPPermission

# book視圖處理類
class Booklist(ModelViewSet):
    permission_classes = [SVIPPermission,]

    queryset = models.Book.objects.all()
    serializer_class = BooklistSerializer

四趋惨、基于RestFramework的認(rèn)證組件做視圖處理類的訪問頻率限制

1鸟顺、訪問頻率限制和認(rèn)證、權(quán)限的執(zhí)行流程一樣器虾,都是restframework源碼提供的一種書寫格式讯嫂,再此就不一一贅述。

  • app001-utils-throttle_classes.py
import time
from rest_framework.throttling import BaseThrottle

VISIT_RECORD = {}

class VisitThrottle(BaseThrottle):

    def __init__(self):
        self.history = None

    def allow_request(self, request, view):
        # 1. 拿到用戶請(qǐng)求的IP
        # print(request.META)
        ip = request.META.get("REMOTE_ADDR")
        # 2. 當(dāng)前請(qǐng)求的時(shí)間
        now = time.time()
        # 3. 記錄訪問的歷史
        if ip not in VISIT_RECORD:
            VISIT_RECORD[ip] = []

        history = VISIT_RECORD[ip]
        self.history = history
        # [11:07:20, 10:07:11, 10:07:06, 10:07:01]
        while history and now - history[-1] > 60:
            history.pop()
        # 判斷用戶在一分鐘的時(shí)間間隔內(nèi)是否訪問超過3次
        if len(history) >= 3:
            return False
        history.insert(0, now)

        return True

    def wait(self):
        # 當(dāng)前訪問時(shí)間
        ctime = time.time()
        #  訪問時(shí)間歷史記錄 self.history
        return 60 - (ctime - self.history[-1])
  • view.py
from app001 import models
from app001.serializers.bookserializer import BooklistSerializer
# 重裝了APIView
from rest_framework.viewsets import ModelViewSet
from app001.utils.throttle_classes import VisitThrottle

# book視圖處理類
class Booklist(ModelViewSet):
    throttle_classes = [VisitThrottle, ]

    queryset = models.Book.objects.all()
    serializer_class = BooklistSerializer

2兆沙、基于RestFramework給我們提供了幾種頻率控制組件欧芽,省去了我們?cè)谧约簩懥?/h4>
  • SimpleRateThrottle類,A simple cache implementation, that only requires .get_cache_key()
    to be overridden.
  • AnonRateThrottle類葛圃,Limits the rate of API calls that may be made by a anonymous users.
  • UserRateThrottle類千扔,Limits the rate of API calls that may be made by a given user.
  • ScopedRateThrottle類,Limits the rate of API calls by different amounts for various parts of
    the API.

app001-utils-throttle_classes.py

from rest_framework.throttling import SimpleRateThrottle

class VisitThrottle(SimpleRateThrottle):
    scope="visit_rate"

    def get_cache_key(self,request, view):
        return self.get_ident(request)

settings.py

REST_FRAMEWORK = {
    "DEFAULT_THROTTLE_CLASSES": ("app001.utils.throttle_classes.VisitThrottle",),
    "DEFAULT_THROTTLE_RATES": {
        "visit_rate": "10/m",//頻率設(shè)置
    },
}

view.py

from app001 import models
from app001.serializers.bookserializer import BooklistSerializer
# 重裝了APIView
from rest_framework.viewsets import ModelViewSet
from app001.utils.throttle_classes import VisitThrottle

# book視圖處理類
class Booklist(ModelViewSet):
    throttle_classes = [VisitThrottle, ]

    queryset = models.Book.objects.all()
    serializer_class = BooklistSerializer

五库正、基于RestFramework的視圖處理類的分頁組件

Restframework提供了幾種很好的分頁方式:

  • 基于頁碼的分頁的 PageNumberPagination類
  • 基于limit offset 做分頁的 LimitOffsetPagination類
  • 基于游標(biāo)的分頁的 CursorPagination類曲楚。但這種方式存在性能問題,如果用戶吧page給改的很大诀诊,查詢速度就會(huì)很慢洞渤。還有一種頁碼加密的方式

1、PageNumberPagination類的使用

  • 方法一属瓣、視圖類繼承APIView時(shí)
    -- 參考的API:
    GET請(qǐng)求:http://127.0.0.1:8000/booklist/?page=2
from rest_framework.views import APIView
from app001 import models
# rest_framework重裝的response
from rest_framework.response import Response
from app001.serializers.bookserializer import BooklistSerializer
from rest_framework.pagination import PageNumberPagination

class Booklist(APIView):

    def get(self, request):
        class MyPageNumberPagination(PageNumberPagination):
            page_ size = 2    //指定的每頁顯示數(shù)
            page_query_param = "page"      //url欄的頁碼參數(shù)
            page_size_query_param = "size"     //獲取url參數(shù)中設(shè)置的每頁顯示數(shù)據(jù)條數(shù)
            max_page_size = 5       //最大支持的每頁顯示的數(shù)據(jù)條數(shù)

        book_obj = models.Book.objects.all()
        # 實(shí)例化
        pnp = MyPageNumberPagination()
        # 分頁
        paged_book_list = pnp.paginate_queryset(book_obj, request)
        bs = BooklistSerializer(paged_book_list, many=True)
        data = bs.data  # 序列化接口
        return Response(data)
  • 方式二载迄、視圖類繼承ModelViewSet時(shí)(少用)
from rest_framework.viewsets import ModelViewSet
from rest_framework.pagination import PageNumberPagination
class MyPageNumberPagination(PageNumberPagination):
    page_size = 3

# book視圖處理
class Booklist(ModelViewSet):
    pagination_class = MyPageNumberPagination

    queryset = models.Book.objects.all()
    serializer_class = BooklistSerializer

2、LimitOffsetPagination類的使用

  • 這種分頁樣式反映了查找多個(gè)數(shù)據(jù)庫記錄時(shí)使用的語法抡蛙』っ粒客戶端包含 “l(fā)imit” 和 “offset” 查詢參數(shù)。limit 表示要返回的 數(shù)據(jù) 的最大數(shù)量粗截,并且等同于其他樣式中的 page_size惋耙。offset 指定查詢的起始位置與完整的未分類 數(shù)據(jù) 集的關(guān)系。多用于返回的內(nèi)容是靜態(tài)的,或者不用實(shí)時(shí)返回?cái)?shù)據(jù)最新的變化绽榛。Google Search 和一些論壇用了這種方式:
  • 參考API:
    GET請(qǐng)求:http://127.0.0.1:8000/booklist/?limit=3&offset=3
    Response響應(yīng):{ "count": 7,"next": "http://127.0.0.1:8000/booklist/?limit=3&offset=6", "previous": "http://127.0.0.1:8000/booklist/?limit=3","results": [...]
from app001 import models
from app001.serializers.bookserializer import BooklistSerializer
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.pagination import LimitOffsetPagination

class MyPageNumberPagination(LimitOffsetPagination):
    max_limit = 3  # 最大限制默認(rèn)是None
    default_limit = 2  # 設(shè)置每一頁顯示多少條
    limit_query_param = 'limit'  # 往后取幾條
    offset_query_param = 'offset'  # 當(dāng)前所在的位置

class Booklist(APIView):

    def get(self, request):
        book_obj = models.Book.objects.all()
        # 實(shí)例化
        pnp = MyPageNumberPagination()
        # 分頁
        paged_book_list = pnp.paginate_queryset(book_obj, request)
        bs = BooklistSerializer(paged_book_list, many=True)
        data = bs.data  # 序列化接口
        # return Response(data) #不含上一頁下一頁
        return pnp.get_paginated_response(data)
  • LimitOffsetPagination 類包含一些可以被覆蓋以修改分頁樣式的屬性湿酸。要設(shè)置這些屬性,應(yīng)該繼承 LimitOffsetPagination 類灭美,然后像上面那樣啟用你的自定義分頁類推溃。
    default_limit- 一個(gè)數(shù)字值,指定客戶端在查詢參數(shù)中未提供的 limit 届腐。默認(rèn)值與 PAGE_SIZE setting key 相同铁坎。
    limit_query_param - 一個(gè)字符串值,指示 “l(fā)imit” 查詢參數(shù)的名稱犁苏。默認(rèn)為 'limit'硬萍。
    offset_query_param - 一個(gè)字符串值,指示 “offset” 查詢參數(shù)的名稱围详。默認(rèn)為 'offset'朴乖。
    max_limit - 一個(gè)數(shù)字值,表示客戶端可以要求的最大允許 limit助赞。默認(rèn)為 None寒砖。
- 了解LIMIT / OFFSET的實(shí)際工作原理。為此嫉拐,我們舉例說明,假如有大約1000個(gè)符合要求的結(jié)果魁兼。你若要前100數(shù)據(jù)婉徘,這很容易,這意味著它只返回與結(jié)果集匹配的前100行咐汞。但是現(xiàn)在想要900-1000之間的數(shù)據(jù)盖呼。數(shù)據(jù)庫現(xiàn)在必須遍歷前900個(gè)結(jié)果才能開始返回(因?yàn)樗鼪]有指針告訴它如何獲得結(jié)果900)』海總之几晤,LIMIT / OFFSET在大型結(jié)果集上非常慢。

3植阴、CursorPagination類的使用

  • 現(xiàn)在很多場(chǎng)景蟹瘾,查詢結(jié)果在用戶瀏覽過程中是變化的,例如微博時(shí)間線掠手,用戶看的時(shí)候憾朴,可能后一頁的某些微博會(huì)被刪除,而前一頁又增添了新的微博喷鸽。這種情況就不適合用 limitoffset分頁方式了众雷。Facebook 和 Twitter 都采用了基于游標(biāo)的分頁方法。
  • 這種方式有以下兩個(gè)特點(diǎn):
    -- 1. 查詢的結(jié)果流可能是動(dòng)態(tài)變化的,例如: 時(shí)間線里出現(xiàn)了新的數(shù)據(jù)砾省,或者刪除了數(shù)據(jù)鸡岗,這些變化都可以在 “前一頁” 或者 “后一頁” 上體現(xiàn)出來。
    -- 2. Cursor 體現(xiàn)了排序编兄,是持久化的轩性。一般情況下 Cursor 的順序是和時(shí)間有關(guān)。如果你的實(shí)體(例如:微博)可能展現(xiàn)給用戶多種可能的排序(例如:創(chuàng)建時(shí)間或者修改時(shí)間)翻诉,那么則需要?jiǎng)?chuàng)建不同的 Cursor炮姨。
    具體實(shí)現(xiàn)時(shí),Cursor 可能分別創(chuàng)建自 創(chuàng)建用戶 或者 修改用戶 字段碰煌。Facebook Relay 用了查詢名稱 + 時(shí)間戳 的 Base64 形式來做 Cursor舒岸。
  • CursorPagination 類包含一些可以被覆蓋以修改分頁樣式的屬性。
    要設(shè)置這些屬性芦圾,你應(yīng)該繼承 CursorPagination 類蛾派,然后像上面那樣啟用你的自定義分頁類。
    -- page_size = 指定頁面大小的數(shù)字值个少。如果設(shè)置洪乍,則會(huì)覆蓋 PAGE_SIZE 設(shè)置。默認(rèn)值與 PAGE_SIZE setting key 相同夜焦。
    -- cursor_query_param = 一個(gè)字符串值壳澳,指定 “游標(biāo)” 查詢參數(shù)的名稱。默認(rèn)為 'cursor'.
    -- ordering = 這應(yīng)該是一個(gè)字符串或字符串列表茫经,指定將應(yīng)用基于游標(biāo)的分頁的字段巷波。例如: ordering = 'slug'。默認(rèn)為 -created卸伞。該值也可以通過在視圖上使用 OrderingFilter 來覆蓋抹镊。
-關(guān)于限制偏移量和游標(biāo)分頁的分析 請(qǐng)參考:http://cra.mr/2011/03/08/building-cursors-for-the-disqus-api

六、基于RestFramework的視圖處理類響應(yīng)器

  • restframework可以根據(jù)url的不同來源做出不同的響應(yīng)荤傲,比如說垮耳,當(dāng)來自瀏覽器端的請(qǐng)求,會(huì)返回一個(gè)頁面遂黍,當(dāng)請(qǐng)求來自于postman等請(qǐng)求軟件時(shí)终佛,返回的是json數(shù)據(jù),這樣的效果是restframework的響應(yīng)器在控制雾家,settings中可以按需配置:
REST_FRAMEWORK={
    'DEFAULT_RENDERER_CLASSES': (
        'rest_framework.renderers.JSONRenderer',  //響應(yīng)json
        'rest_framework.renderers.BrowsableAPIRenderer',   //響應(yīng)頁面
    ),
}

七查蓉、基于RestFramework的視圖處理類的url注冊(cè)器

url注冊(cè)器只是適用于視圖類繼承ModelViewSet類的寫法:
url注冊(cè)器會(huì)生成四條url:
^ ^booklist/$ [name='book-list']
^ ^booklist\.(?P<format>[a-z0-9]+)/?$ [name='book-list'] //可以指定數(shù)據(jù)類型
^ ^booklist/(?P<pk>[^/.]+)/$ [name='book-detail']
^ ^booklist/(?P<pk>[^/.]+)\.(?P<format>[a-z0-9]+)/?$ [name='book-detail'] //可以指定單個(gè)數(shù)據(jù)數(shù)據(jù)類型
urls.py

from rest_framework import routers
router = routers.DefaultRouter() //實(shí)例化
router.register("booklist", views.Booklist)   //注冊(cè)

urlpatterns = [
    url(r'^', include(router.urls)),
]

view.py

from app001 import models
from app001.serializers.bookserializer import BooklistSerializer
# 重裝了APIView
from rest_framework.viewsets import ModelViewSet

# book視圖處理類
class Booklist(ModelViewSet):

    queryset = models.Book.objects.all()
    serializer_class = BooklistSerializer
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市榜贴,隨后出現(xiàn)的幾起案子豌研,更是在濱河造成了極大的恐慌妹田,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件鹃共,死亡現(xiàn)場(chǎng)離奇詭異鬼佣,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)霜浴,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門晶衷,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人阴孟,你說我怎么就攤上這事晌纫。” “怎么了永丝?”我有些...
    開封第一講書人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵锹漱,是天一觀的道長。 經(jīng)常有香客問我慕嚷,道長哥牍,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任喝检,我火速辦了婚禮嗅辣,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘挠说。我一直安慰自己澡谭,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開白布损俭。 她就那樣靜靜地躺著译暂,像睡著了一般。 火紅的嫁衣襯著肌膚如雪撩炊。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,292評(píng)論 1 301
  • 那天崎脉,我揣著相機(jī)與錄音拧咳,去河邊找鬼。 笑死囚灼,一個(gè)胖子當(dāng)著我的面吹牛骆膝,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播灶体,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼阅签,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了蝎抽?” 一聲冷哼從身側(cè)響起政钟,我...
    開封第一講書人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后养交,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體精算,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年碎连,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了灰羽。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡鱼辙,死狀恐怖廉嚼,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情倒戏,我是刑警寧澤怠噪,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站峭梳,受9級(jí)特大地震影響舰绘,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜葱椭,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一捂寿、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧孵运,春花似錦秦陋、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至旷赖,卻和暖如春顺又,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背等孵。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來泰國打工稚照, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人俯萌。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓果录,卻偏偏與公主長得像,于是被迫代替她去往敵國和親咐熙。 傳聞我的和親對(duì)象是個(gè)殘疾皇子弱恒,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354

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