django-rest-framework(實(shí)戰(zhàn)篇)——tutorial

一扔字、序列化

創(chuàng)建模型類:

創(chuàng)建一個(gè)Snippet模型類革为,用于儲(chǔ)存代碼段舵鳞,編寫snippets/models.py:

from django.db import models
from pygments.lexers import get_all_lexers
from pygments.styles import get_all_styles

LEXERS = [item for item in get_all_lexers() if item[1]]
LANGUAGE_CHOICES = sorted([(item[1][0], item[0]) for item in LEXERS])  # 得到所有的編程語言
STYLE_CHOICES = sorted((item, item) for item in get_all_styles())  # 得到所有的配色風(fēng)格


class Snippet(models.Model):
    created = models.DateTimeField(auto_now_add=True)
    title = models.CharField(max_length=100, blank=True, default='')
    code = models.TextField()
    linenos = models.BooleanField(default=False)
    language = models.CharField(choices=LANGUAGE_CHOICES, default='python', max_length=100)
    style = models.CharField(choices=STYLE_CHOICES, default='friendly', max_length=100)

    class Meta:
        ordering = ('created',)

遷移到數(shù)據(jù)庫(kù):

python manage.py makemigrations snippets
python manage.py migrate

創(chuàng)建序列化類

首先解釋一下序列化:在這里可以先簡(jiǎn)單的理解為serializer把模型實(shí)例轉(zhuǎn)化為json格式然后響應(yīng)出去,這樣便于客戶端調(diào)用時(shí)解析使用抛虏。

那么反序列化其實(shí)道理差不多,反序列化之后的數(shù)據(jù)格式更便于后臺(tái)使用迂猴。

from rest_framework import serializers
from snippets.models import Snippet, LANGUAGE_CHOICES, STYLE_CHOICES


class SnippetSerializer(serializers.Serializer):
    id = serializers.IntegerField(read_only=True)
    title = serializers.CharField(required=False, allow_blank=True, max_length=100)
    # 利用字段標(biāo)志控制序列化器渲染到HTML頁(yè)面時(shí)的的顯示模板
    code = serializers.CharField(style={'base_template': 'textarea.html'})
    linenos = serializers.BooleanField(required=False)
    language = serializers.ChoiceField(choices=LANGUAGE_CHOICES, default='python')
    style = serializers.ChoiceField(choices=STYLE_CHOICES, default='friendly')

    # 給定經(jīng)過驗(yàn)證的數(shù)據(jù),創(chuàng)建并返回一個(gè)新的 Snippet 實(shí)例
    def create(self, validated_data):
        return Snippet.objects.create(**validated_data)

    # 給定經(jīng)過驗(yàn)證的數(shù)據(jù)峰髓,更新并返回一個(gè)已經(jīng)存在的 Snippet 實(shí)例
    def update(self, instance, validated_data):
        instance.title = validated_data.get('title', instance.title)
        instance.code = validated_data.get('code', instance.code)
        instance.linenos = validated_data.get('linenos', instance.linenos)
        instance.language = validated_data.get('language', instance.language)
        instance.style = validated_data.get('style', instance.style)
        instance.save()
        return instance

使用ModelSerializers

在上面的SnippetSerializer類中息尺,我們繼承的是serializers.Serializer類,可以看到SnippetSerializer類中有很多代碼其實(shí)是和models.py中的Snippet模型類似一樣的搂誉,所以這里我們可以改進(jìn)一下。就像在Django中提供了Form類和ModelForm類一樣,django-rest-framework為我們提供了Serializer類和ModelSerializer類巴柿。利用它可以讓我們的代碼簡(jiǎn)潔很多,修改serializers.py:

class SnippetSerializer(serializers.ModelSerializer):
    class Meta:
        model = Snippet
        fields = ('id', 'title', 'code', 'linenos', 'language', 'style')

編寫常規(guī)的Django視圖

from django.http import HttpResponse, JsonResponse
from django.views.decorators.csrf import csrf_exempt
from rest_framework.renderers import JSONRenderer
from rest_framework.parsers import JSONParser
from snippets.models import Snippet
from snippets.serializers import SnippetSerializer


# Create your views here.
@csrf_exempt
def snippet_list(request):
    """
    列出所有已經(jīng)存在的snippet或者創(chuàng)建一個(gè)新的snippet
    """
    if request.method == 'GET':
        snippets = Snippet.objects.all()
        serializer = SnippetSerializer(snippets, many=True)
        return JsonResponse(serializer.data, safe=False)

    elif request.method == 'POST':
        data = JSONParser().parse(request)
        serializer = SnippetSerializer(data=data)
        if serializer.is_valid():
            serializer.save()
            return JsonResponse(serializer.data, status=201)
        return JsonResponse(serializer.errors, status=400)


@csrf_exempt
def snippet_detail(request, pk):
    """
    檢索查看凯旋、更新或者刪除一個(gè)代碼段
    """
    try:
        snippet = Snippet.objects.get(pk=pk)
    except Snippet.DoesNotExist:
        return HttpResponse(status=404)

    if request.method == 'GET':
        serializer = SnippetSerializer(snippet)
        return JsonResponse(serializer.data)

    elif request.method == 'PUT':
        data = JSONParser().parse(request)
        serializer = SnippetSerializer(snippet, data=data)
        if serializer.is_valid():
            serializer.save()
            return JsonResponse(serializer.data)
        return JsonResponse(serializer.errors, status=400)

    elif request.method == 'DELETE':
        snippet.delete()
        return HttpResponse(status=204)

配置urls:
先創(chuàng)建snippets/urls.py

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

urlpatterns = [
    url(r'^snippets/$', views.snippet_list),
    url(r'^snippets/(?P<pk>[0-9]+)/$', views.snippet_detail),
]

接著就是tutorial/urls.py

from django.conf.urls import url, include

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

二至非、請(qǐng)求和響應(yīng)

精簡(jiǎn)view.py中的代碼:

from rest_framework import status
from rest_framework.decorators import api_view
from rest_framework.response import Response
from snippets.models import Snippet
from snippets.serializers import SnippetSerializer


@api_view(['GET', 'POST'])
def snippet_list(request):
    """
    列出所有已經(jīng)存在的snippet或者創(chuàng)建一個(gè)新的snippet
    """
    if request.method == 'GET':
        snippets = Snippet.objects.all()
        serializer = SnippetSerializer(snippets, many=True)
        return Response(serializer.data)

    elif request.method == 'POST':
        serializer = SnippetSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

@api_view(['GET', 'PUT', 'DELETE'])
def snippet_detail(request, pk):
    """
    Retrieve, update or delete a snippet instance.
    """
    try:
        snippet = Snippet.objects.get(pk=pk)
    except Snippet.DoesNotExist:
        return Response(status=status.HTTP_404_NOT_FOUND)

    if request.method == 'GET':
        serializer = SnippetSerializer(snippet)
        return Response(serializer.data)

    elif request.method == 'PUT':
        serializer = SnippetSerializer(snippet, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    elif request.method == 'DELETE':
        snippet.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

和上一個(gè)版本對(duì)比有如下不同:

  • Request對(duì)象:

平時(shí)我們?cè)趯慏jango的視圖函數(shù)的時(shí)候,都會(huì)帶上一個(gè)request參數(shù)舰蟆,這樣就能處理平時(shí)搭建網(wǎng)站時(shí)身害,瀏覽器訪問網(wǎng)頁(yè)時(shí)發(fā)出的常規(guī)的HttpRequest塌鸯。但是現(xiàn)在我們導(dǎo)入了django-rest-framework丙猬,它能夠?qū)equest進(jìn)行拓展,并且提供更靈活的請(qǐng)求解析咐低。這個(gè)特性體現(xiàn)在哪呢见擦?請(qǐng)看下面這個(gè)例子:

request.POST  # 只能處理表單數(shù)據(jù).只能處理POST請(qǐng)求
request.data  # 能處理各種數(shù)據(jù)损痰。  可以處理'POST', 'PUT' 和 'PATCH'模式的請(qǐng)求

拓展后的request使用request.data就可以處理各種各樣的請(qǐng)求了酒来,而原本的request在處理時(shí)需要指定請(qǐng)求模式堰汉。

  • Response對(duì)象:

和request對(duì)象一樣,django-rest-framework也對(duì)其進(jìn)行了很實(shí)用的拓展翘鸭,在上一個(gè)版本中,我們導(dǎo)入了JsonResponse用于返回json格式的響應(yīng)就乓。

也就是說,在return的時(shí)候就需要指明json格式噩翠,這樣顯得很不實(shí)用而且很單一,所以經(jīng)過拓展后的Reponse對(duì)象就很方便了伤锚,它會(huì)根據(jù)客戶端的請(qǐng)求頭部信息來確定正確的內(nèi)容類型以返回給客戶端。只需如下代碼:

return Response(data)
  • 狀態(tài)碼

  • 裝飾API視圖

三见芹、基于類的視圖CBV(Class Basic View)

這里要做的是把基于方法的視圖改為基于類的視圖蠢涝,我們將會(huì)了解到APIView
重構(gòu)一下snippets/view.py:

from snippets.models import Snippet
from snippets.serializers import SnippetSerializer
from django.http import Http404
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status


class SnippetList(APIView):
    """
    列出所有已經(jīng)存在的snippet或者創(chuàng)建一個(gè)新的snippet
    """
    def get(self, request, format=None):
        snippets = Snippet.objects.all()
        serializer = SnippetSerializer(snippets, many=True)
        return Response(serializer.data)

    def post(self, request, format=None):
        serializer = SnippetSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

和原來的相比,可以發(fā)現(xiàn)基于類的視圖把各種不同的HTTP請(qǐng)求分離開變成單個(gè)的方法和二,而不是if...elif...這樣的結(jié)構(gòu),所以這樣處理起來很更加的高效惕它。

class SnippetDetail(APIView):
    """
    檢索查看、更新或者刪除一個(gè)snippet
    """
    def get_object(self, pk):
        try:
            return Snippet.objects.get(pk=pk)
        except Snippet.DoesNotExist:
            raise Http404

    def get(self, request, pk, format=None):
        snippet = self.get_object(pk)
        serializer = SnippetSerializer(snippet)
        return Response(serializer.data)

    def put(self, request, pk, format=None):
        snippet = self.get_object(pk)
        serializer = SnippetSerializer(snippet, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    def delete(self, request, pk, format=None):
        snippet = self.get_object(pk)
        snippet.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

改為基于類的視圖之后淹魄,修改一下路由了,對(duì)snippets/urls.py稍加修改:

from django.conf.urls import url
from rest_framework.urlpatterns import format_suffix_patterns
from snippets import views

urlpatterns = [
    url(r'^snippets/$', views.SnippetList.as_view()),
    url(r'^snippets/(?P<pk>[0-9]+)/$', views.SnippetDetail.as_view()),
]

使用Mixins類+GenericAPIView類

rom snippets.models import Snippet
from snippets.serializers import SnippetSerializer
from rest_framework import mixins
from rest_framework import generics

class SnippetList(mixins.ListModelMixin,
                  mixins.CreateModelMixin,
                  generics.GenericAPIView):
    queryset = Snippet.objects.all()
    serializer_class = SnippetSerializer

    def get(self, request, *args, **kwargs):
        return self.list(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        return self.create(request, *args, **kwargs)

新的視圖類中繼承了 generic.GenericAPIView兆蕉、mixins.ListModelMixin和mixins.CreatteModelMixin缤沦,mixins類為我們提供了list()和create()方法,當(dāng)然缸废,使用這兩個(gè)函數(shù)需要先重載GenericAPIView中的queryset和serializer_class屬性,這點(diǎn)我們查看一下mixins的源碼就可以看出來了企量。比如list方法會(huì)分別通過get_queryset()和get_serializer()得到查詢集和序列化器,其他封裝好的方法也是如此届巩。

修改另外一個(gè)視圖:

class SnippetDetail(mixins.RetrieveModelMixin,
                    mixins.UpdateModelMixin,
                    mixins.DestroyModelMixin,
                    generics.GenericAPIView):
    queryset = Snippet.objects.all()
    serializer_class = SnippetSerializer

    def get(self, request, *args, **kwargs):
        return self.retrieve(request, *args, **kwargs)

    def put(self, request, *args, **kwargs):
        return self.update(request, *args, **kwargs)

    def delete(self, request, *args, **kwargs):
        return self.destroy(request, *args, **kwargs)

使用通用的視圖類

進(jìn)一步精簡(jiǎn)代碼:

from snippets.models import Snippet
from snippets.serializers import SnippetSerializer
from rest_framework import generics


class SnippetList(generics.ListCreateAPIView):
    queryset = Snippet.objects.all()
    serializer_class = SnippetSerializer


class SnippetDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Snippet.objects.all()
    serializer_class = SnippetSerializer

通過源碼可知,ListCreateAPIView和RetrieveUpdateDestroyAPIView只是對(duì)上一個(gè)版本代碼的簡(jiǎn)單封裝。

四冒嫡、ViewSets和Routers

在第一部分和第二部分中寫的編寫Django視圖時(shí),使用的都是基于函數(shù)的方法孝凌,并且每個(gè)視圖函數(shù)之前都會(huì)加一個(gè)django-rest-framework帶的裝飾器@api_view。然后在第三部分蟀架,我們就開始把基于函數(shù)的視圖改成了基于類的視圖,然后發(fā)現(xiàn)這樣做視圖部分減少了很多代碼量片拍。

使用ViewSet重構(gòu)視圖

拿本項(xiàng)目為例子,我們之前查看所有snippet列表就要寫一個(gè)視圖類SnippetList苫纤,并在urls.py中為其設(shè)置一個(gè)模式然后as_view使用它,然后要看單個(gè)用戶的詳情頁(yè)就要再寫一個(gè)SnippetDetail視圖類并再在添加一個(gè)url模式污筷。同時(shí)注意到這兩個(gè)視圖類都是繼承的generics.XXXAPIView。而使用ViewSets我們就可以把SnippetList和SnippetDetail合并成SnippetViewSet視圖類耿焊,并且繼承的類改為viewsets.ModelViewSet器腋,這樣就是一個(gè)視圖集了纫塌。

class SnippetViewSet(viewsets.ModelViewSet):
    """
    viewset自動(dòng)提供了`list`, `create`, `retrieve`,  `update` 和 `destroy` 動(dòng)作.
    """
    queryset = Snippet.objects.all()
    serializer_class = SnippetSerializer

將ViewSets明確的綁定到URL

每個(gè)視圖集的url模式都需要我們?cè)赼s_view中傳入?yún)?shù)避除,把snippets/urls.py的代碼換成下面的:

from django.conf.urls import url,include
from snippets.views import SnippetViewSet

snippet_list = SnippetViewSet.as_view({
    'get': 'list',
    'post': 'create'
})
snippet_detail = SnippetViewSet.as_view({
    'get': 'retrieve',
    'put': 'update',
    'patch': 'partial_update',
    'delete': 'destroy'
})

urlpatterns = format_suffix_patterns([
    url(r'^snippets/$', snippet_list, name='snippet-list'),
    url(r'^snippets/(?P<pk>[0-9]+)/$', snippet_detail, name='snippet-detail'),

使用Routers

from django.conf.urls import url, include
from snippets import views
from rest_framework.routers import DefaultRouter

# Create a router and register our viewsets with it.
router = DefaultRouter()
router.register(r'snippets', views.SnippetViewSet)

# The API URLs are now determined automatically by the router.
# Additionally, we include the login URLs for the browsable API.
urlpatterns = [
    url(r'^', include(router.urls)),
]

五、權(quán)限和認(rèn)證

Object

  • snippets 與User相關(guān)聯(lián)
  • 只有登錄的用戶才可以創(chuàng)建snippets
  • 只有創(chuàng)建該snippets的用戶有編輯權(quán)限
  • 未登錄的用戶只有訪問的權(quán)限

修改Snippets Model

在Snippet模型添加一個(gè)owner字段作為外鍵

owner = models.ForeignKey('auth.User', related_name='snippets', on_delete=models.CASCADE)

添加UserSerializer

在snippets/serializers.py中添加一個(gè)User序列化器:

class UserSerializer(serializers.ModelSerializer):
    snippets = serializers.PrimaryKeyRelatedField(many=True, queryset=Snippet.objects.all())

    class Meta:
        model = User
        fields = ('id', 'username', 'snippets')

owner是snippet的外鍵状飞,可以通過Snippet正向查詢到owner字段的數(shù)據(jù),而snippet在User模型中是一個(gè)反向關(guān)系焙糟,User這邊查詢不到用戶創(chuàng)建的snippet酬荞,所以我們需要手動(dòng)為UserSerializer添加snippets字段枪向。

添加相應(yīng)的UserView

class UserList(generics.ListAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer


class UserDetail(generics.RetrieveAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer

路由分發(fā)

url(r'^users/$', views.UserList.as_view()),
url(r'^users/(?P<pk>[0-9]+)/$', views.UserDetail.as_view()),

關(guān)聯(lián)Snippets和Users

如果像之前那樣創(chuàng)建代碼段的話,我們還不能把Snippets和Users關(guān)聯(lián)起來深员。因?yàn)樵谑褂玫臅r(shí)候User的數(shù)據(jù)是通過request傳入的,而不是以序列化的數(shù)據(jù)傳遞過來叠赐。

class SnippetList(generics.ListCreateAPIView):
    queryset = Snippet.objects.all()
    serializer_class = SnippetSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

    def perform_create(self, serializer):
        serializer.save(owner=self.request.user)

這個(gè)perform_create() 可以讓用戶在通過POST請(qǐng)求創(chuàng)建一個(gè)新的Snippet時(shí),會(huì)把request中的user賦值給Snippet的owner惩嘉。

為了提高可讀性惹苗,在API中要讓owner顯示用戶名桩蓉,所以我們?cè)赟nippetSerializer 下面增加一個(gè)字段:

    owner = serializers.CharField(read_only=True, source='owner.username')

source參數(shù)指明顯示owner模型的哪一個(gè)字段

添加權(quán)限

現(xiàn)在Snippet和User已經(jīng)關(guān)聯(lián)起來并且是可瀏覽的玷或。接下來實(shí)現(xiàn)權(quán)限判斷:

from rest_framework import permissions

# 在SnippetList和SnippetDetail類中加入
permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

功能:驗(yàn)證當(dāng)前用戶是否Login片任,若是位他,則可以創(chuàng)建Snippet鹅髓,編輯(包括修改窿冯、刪除)某一個(gè)具體的Snippet执桌,若否,則只能瀏覽Snippet膘壶。

添加對(duì)象權(quán)限

接著我們要實(shí)現(xiàn)的是每個(gè)Snippet只有其創(chuàng)建者才可以對(duì)其進(jìn)行更改香椎、刪除等操作畜伐。因此,我們需要設(shè)置一下自定義權(quán)限慎框,使每個(gè)Snippet只允許其創(chuàng)建者編輯它笨枯。在snippets目錄下新建一個(gè)permissions.py:

from rest_framework import permissions


class IsOwnerOrReadOnly(permissions.BasePermission):
    """
    使每個(gè)Snippet只允許其創(chuàng)建者編輯它
    """

    def has_object_permission(self, request, view, obj):

    # 任何用戶或者游客都可以訪問任何Snippet粱檀,所以當(dāng)請(qǐng)求動(dòng)作在安全范圍內(nèi)茄蚯,
    # 也就是GET,HEAD汗盘,OPTIONS請(qǐng)求時(shí)衡未,都會(huì)被允許
        if request.method in permissions.SAFE_METHODS:
            return True

    # 而當(dāng)請(qǐng)求不是上面的安全模式的話绊诲,那就需要判斷一下當(dāng)前的用戶
    # 如果Snippet所有者和當(dāng)前的用戶一致,那就允許,否則返回錯(cuò)誤信息
        return obj.owner == request.user

六动雹、添加超鏈接

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市茸塞,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌笋庄,老刑警劉巖菌仁,帶你破解...
    沈念sama閱讀 218,682評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件籍嘹,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡泪掀,警方通過查閱死者的電腦和手機(jī)异赫,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人适掰,你說我怎么就攤上這事载城∷咄撸” “怎么了?”我有些...
    開封第一講書人閱讀 165,083評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵猴贰,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我栅干,道長(zhǎng),這世上最難降的妖魔是什么窿给? 我笑而不...
    開封第一講書人閱讀 58,763評(píng)論 1 295
  • 正文 為了忘掉前任禁荒,我火速辦了婚禮呛伴,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘褐隆。我一直安慰自己庶弃,他們只是感情好梆造,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,785評(píng)論 6 392
  • 文/花漫 我一把揭開白布屡穗。 她就那樣靜靜地躺著村砂,像睡著了一般罕模。 火紅的嫁衣襯著肌膚如雪淑掌。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,624評(píng)論 1 305
  • 那天侥钳,我揣著相機(jī)與錄音柄错,去河邊找鬼。 笑死敢伸,一個(gè)胖子當(dāng)著我的面吹牛池颈,可吹牛的內(nèi)容都是我干的携丁。 我是一名探鬼主播梦鉴,決...
    沈念sama閱讀 40,358評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼存筏!你這毒婦竟也來了方篮?” 一聲冷哼從身側(cè)響起匕得,我...
    開封第一講書人閱讀 39,261評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎考阱,沒想到半個(gè)月后乞榨,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體秽之,經(jīng)...
    沈念sama閱讀 45,722評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡考榨,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年鹦倚,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片震叙。...
    茶點(diǎn)故事閱讀 40,030評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖媒楼,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情匣砖,我是刑警寧澤,帶...
    沈念sama閱讀 35,737評(píng)論 5 346
  • 正文 年R本政府宣布猴鲫,位于F島的核電站,受9級(jí)特大地震影響拂共,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,360評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸飘庄。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)掂榔。三九已至穴豫,卻和暖如春溉仑,著一層夾襖步出監(jiān)牢的瞬間怨喘,已是汗流浹背梳庆。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留征峦,地道東北人竖伯。 一個(gè)月前我還...
    沈念sama閱讀 48,237評(píng)論 3 371
  • 正文 我出身青樓贺辰,卻偏偏與公主長(zhǎng)得像硫眨,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,976評(píng)論 2 355

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