实例:django实现博客小项目

封面.jpg

前面已经对DTL(Django Template Language)语言基础用法进行了讲解,现在我们开始做一个博客小项目。

1. 准备工作

首先,我们整理一下整个流程,一个简单的博客项目包含博客列表页、博客详情页、博客编辑页、添加博客页,其页面设计如下:

页面设计(Page):
1.博客列表页:所有博客文章列表、写博客按钮                 blog/index                          index.html
2.博客详情页:标题、内容、编辑按钮                        blog/article/article_id             article_page.html
3.博客编辑页:form表单、标题、内容、提交按钮               blog/article/edit                   article_edit_page.html
4.添加博客页:form表单、标题、内容、提交按钮

事件(Action):
编辑博客提交Action:post提交(博客标题、id、内容)
新增博客提交Action:post提交(博客标题、内容)

下面,我们来梳理数据及页面跳转:


页面及数据流转

如上,由于编辑博客、新增博客非常相似,我们就将两个页面合并成一个。

2. 开始编码

1.首先我们创建并配置项目的基本信息

打来终端,找到我们存放python项目的目录python-works(这个存储地址根据你个人喜好选择),然后在终端中输入一下命令:

django-admin startproject myblog

然后cd 到myblog的目录下,执行以下命令

python3 manage.py runserver
启动项目

用浏览器打开http://127.0.0.1:8000/,出现欢迎界面,说明项目创建成功:


欢迎界面

还记得如何把界面修改成中文的吗,进入settings.py,修改以下代码

LANGUAGE_CODE = 'zh-hans'         #将'en-us'改为'zh-hans' 

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True

再刷新一下界面,界面即变成中文,此时准备工作已经做完了,接下来我们开始创建博客应用。

2.创建博客应用

仍然打开终端,进入到myblog目录下,输入以下命令创建一个名为blog的应用:

python3 manage.py startapp  blog

此时项目中多了一个名为blog的应用:


blog创建成功

打开settings.py文件,将blog添加到应用列表中

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'blog',                                          #添加blog应用到应用列表中
]

此时,我们还未创建任何页面,现在blog下的views.py中定义一个index页,输出一行文字,如下

from django.shortcuts import render
from django.http import HttpResponse


def index(request):
    return HttpResponse('我是博客应用页面!')

然后,在myblog文件夹下的urls.py文件中添加一个路径:

from django.conf.urls import url
from django.contrib import admin
from blog.views import index

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^index/', index)           #添加index的路径
]

再重启一下服务,我们访问http://127.0.0.1:8000/index,界面上显示了正确的内容

index

在前面的页面设计中,我们想访问的是blog/index,而不是直接访问index,这个怎么做呢?其实在前面的文章 知识详解2:django之项目下创建应用及注意事项 中有详细的说明,在此不再赘述。我们现在blog下创建一个名为blog_urls.py的文件,然后输入以下内容:

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


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

然后,将系统的urls.py文件修改为

from django.conf.urls import url, include
from django.contrib import admin
from blog.views import index


urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^index/', include('blog.blog_urls')),
]

为什么这么干,可以查看前面的文章 知识详解2:django之项目下创建应用及注意事项

再次刷新一下页面,访问http://127.0.0.1:8000/blog/index,即显示了正确的内容。至此,blog项目的准备工作做完了,接下来我们来创建页面。

3.博客列表页

前面已经在界面上显示了一行文字,但是这个不是我们想要的,我们需要显示一个界面,然后在界面上显示数据库的文章列表,前文 知识详解3:django之创建Template文件 详细讲解了如何创建页面。
首先,我们在blog文件夹下创建一个名为templates的文件夹,并添加一个index.html文件,然后修改blog下的views.py的内容,让views返回index.html

from django.shortcuts import render
from django.http import HttpResponse


def index(request):
    return render(request, 'index.html')              #render函数有三个参数,此处只传了两个

此时,访问http://127.0.0.1:8000/blog/index,显示的是一个空页面,这是因为我们既没有向index.html文件中传递数据,也没有在index.html中写显示数据的逻辑,接下来,我们准备数据源。前文 知识详解4:django之models与数据表 中有详细的解释。
在blog的models.py中创建博客对象,包含title、content两个字端(系统默认会添加一个id),models.py的代码如下:

from django.db import models


class Article(models.Model):
    title = models.CharField(max_length=32, default='')
    # 文章正文,使用的是TextField
    # 存储比较短的字符串可以使用 CharField,但对于文章的正文来说可能会是一大段文本,因此使用 TextField 来存储大段文本。
    content = models.TextField(null=True)

然后在终端中执行以下命令:

python3 manage.py makemigrations

成功后继续执行

python3 manage.py migrate
执行结果

接下来,我们为该项目创建一个名为yucanghai,密码为root123456的超级用户,在登录django后台之前,我们需要在blog下的admin.py中配置一下

from django.contrib import admin
from .models import Article


admin.site.register(Article)      #必须增加这一行,否则进入后台什么都没有

接下来,我们登录后台增加几篇博客,如下:


博客列表

此处显示的全部是Article object,我们调整一下models.py的代码:

from django.db import models
from django.contrib.auth.models import User


class Article(models.Model):
    title = models.CharField(max_length=32, default='')
    # 文章正文,使用的是TextField
    # 存储比较短的字符串可以使用 CharField,但对于文章的正文来说可能会是一大段文本,因此使用 TextField 来存储大段文本。
    content = models.TextField(null=True)
    
    def __str__(self):    #增加该方法
        return self.title

刷新界面,显示如下:


正确显示.png

现在,我们需要将数据库中的博客数据读取出来,显示在index.html文件中。在blog下的views.py文件中读取数据并传递给index.html,调整views.py代码如下:

from django.shortcuts import render
from django.http import HttpResponse
from . import models


def index(request):
    articles = models.Article.objects.all() 
    #这里是取所有,如果取某一个article = models.Article.objects.get(pk=1) 

    return render(request, 'index.html', {'articles': articles})

修改index.html文件,将内容显示出来:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>首页</title>
</head>
<body>
<h3>我的博客列表:</h3>
    {% for article in articles %}    #这是DTL的语法,
        <a href=""> {{ article.title }} </a>    #此处先不添加跳转页面,稍后再添加
        <br/> 
    {% endfor %}    #for循环必须以这个结尾

</body>
</html>

好,我们的博客首页已经完成了,接下来做博客详情页。

4.博客详情页

在templates文件夹下新建一个名为article_page.html的页面,这个页面的作用就是显示博客的详细内容,这个页面的数据就是上一页面传递过来的博客对象,我们先编写显示代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>博客详情页</title>
</head>
<body>
    <h3>标题: {{ article.title }}</h3>
    </br>
    <h3>内容: {{ article.content }}</h3>
</body>
</html>

现在的问题是要从views中将article对象传递给该页面,所以我们在view.py中增加:

from django.shortcuts import render
from django.http import HttpResponse
from . import models


def index(request):
    articles = models.Article.objects.all()
    return render(request, 'index.html', {'articles': articles})


def article_page(request, article_id):        #根据博客id获取博客内容
    article = models.Article.objects.get(pk=article_id)
    return render(request, 'article_page.html', {'article': article})

根据上一个页面传递的article_id获取到这个article对象,并传递给html页面显示出来,那这个article_id该怎么传递过来呢?参照前面的页面设计中,我们的设计是访问博客详情页的地址是 http://127.0.0.1:8000/blog/article/1 ,这个id可以从访问的URL中传递,我们来修改传递的url,打开blog_urls.py文件:

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


urlpatterns = [
    url(r'^index/', views.index),
    url(r'^article/(?P<article_id>[0-9])$', views.article_page),
]

这里正则表达式为何这么些,会在我的文章中有专门的模块来讲,知道这个article_id是这么传递的即可,运行一下服务器,我们访问一下http://127.0.0.1:8000/blog/article/1 是不是可以显示正确的内容了呢。这里需要注意的是DTL下,models自动生成的id的下标是从1开始的,而不是0.
两个页面做好了,我们现在需要在index.html中增加点击标题的跳转链接

第一种方式:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>首页</title>
</head>
<body>
<h3>我的博客列表:</h3>
    {% for article in articles %}
        <a href="../article/{{ article.id }}"> {{ article.title }} </a>
        <br/>
    {% endfor %}

</body>
</html>

再运行一下,刷新页面,可以正常跳转了。但是,这种跳转逻辑是最基础的,但是当应用中有很多页面的时候,这种方式显的不灵活,现在看第二种方法。

第二种方式:

首先,在项目的urls.py中为博客应用增加一个namespace:

from django.conf.urls import url, include
from django.contrib import admin
from blog.views import index


urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^blog/', include('blog.blog_urls', namespace='blog')),
]

然后,在blog_urls.py中为博客详情页增加一个namespace:

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


urlpatterns = [
    url(r'^index/', views.index),
    url(r'^article/(?P<article_id>[0-9]+)$', views.article_page, name='article_page'),
]

这两步操作相当于给博客应用和博客详情页面增加一个别名,为后面调用提供一种快捷方式。我们再回到index.html中,修改href:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>首页</title>
</head>
<body>
<h3>我的博客列表:</h3>
    {% for article in articles %}
        <a href="{% url 'blog:article_page' article.id %}"> {{ article.title }} </a>
        <br/>
    {% endfor %}

</body>
</html>

我们将href修改成DTL的另外一种表达方式,href="{% url 路径 参数 %}",其中路径就是我们前面定义的不同层级namespace由大到小排列,如果没有参数可以不写。
至此,我们的博客首页和详情页已经完善,现在我们需要在博客首页增加一个新增按钮用于跳转到发博客页面,在博客详情页增加一个编辑按钮,用于跳转到博客编辑页面,我们先将index.html修改如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>首页</title>
</head>
<body>
<h3>我的博客列表:</h3>
    {% for article in articles %}
        <a href="{% url 'blog:article_page' article.id %}"> {{ article.title }} </a>
        <br/>
    {% endfor %}

    </br>
    </br>
    <a href="">写博客</a>

</body>
</html>

博客详情页article_page.html修改如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>博客详情页</title>
</head>
<body>
    <h3>标题: {{ article.title }}</h3>
    </br>
    <h3>内容: {{ article.content }}</h3>
    </br>
    </br>
    <a href="">编辑</a>

</body>
</html>

新增博客和编辑博客页面相似,我们就使用同一个页面,接下来我们编写编辑页面。

5.编辑博客页

首先,我们在templates下新建编辑页面article_edit_page.html页面

<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/html">
<head>
    <meta charset="UTF-8">
    <title>编辑博客页面</title>
</head>
<form action="" method="post">
    <label>博客标题
       <input type="text" name="title">
    </label>
    </br>
    <label>博客内容
       <input type="text" name="content">
    </label>
    </br>
    <input type="submit" value="提交">
</form>
<body>

</body>
</html>

这里是定义了一个form表单,用于填写博客标题、内容,并提交,在form中定义了一个action,这个是当提交按钮点击时触发的事件,暂时我们先空着。接下来,我们在views中增加编辑页面的响应函数:

from django.shortcuts import render
from django.http import HttpResponse
from . import models


def index(request):
    articles = models.Article.objects.all()
    return render(request, 'index.html', {'articles': articles})


def article_page(request, article_id):
    article = models.Article.objects.get(pk=article_id)
    return render(request, 'article_page.html', {'article': article})


def article_edit_page(request):
    return render(request, 'blog/article_edit_page.html')  #暂时不传递参数

然后在blog下的blog_urls.py中增加编辑页面的访问路径:

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


urlpatterns = [
    url(r'^index/', views.index),
    url(r'^article/(?P<article_id>[0-9]+)$', views.article_page, name='article_page'),
    url(r'^article/edit/$', views.article_edit_page),
]

OK,我们访问一下http://127.0.0.1:8000/blog/article/edit/ ,此时编辑页面就显示出来了,这个页面暂时是空页面,并为传递任何参数:

编辑页

下面,我们需要增加提交按钮的响应事件,提交按钮点击时需要有一个响应函数,并有访问该函数的路径,所以我们在viwes中增加响应函数:

from django.shortcuts import render
from django.http import HttpResponse
from . import models


def index(request):
    articles = models.Article.objects.all()
    return render(request, 'index.html', {'articles': articles})


def article_page(request, article_id):
    article = models.Article.objects.get(pk=article_id)
    return render(request, 'article_page.html', {'article': article})


def article_edit_page(request):
    return render(request, 'article_edit_page.html')


def article_edit_page_action(request):
    title = request.POST.get('title', '默认标题')     ##get是根据参数名称从form表单页获取内容
    content = request.POST.get('content', '默认内容')
    ##保存数据
    models.Article.objects.create(title=title, content=content)
    ##数据保存完成,返回首页
    articles = models.Article.objects.all()
    return render(request, 'index.html', {'articles': articles})

再为响应函数增加访问路径,打开blog下的blog_urls.py,修改如下:

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


urlpatterns = [
    url(r'^index/', views.index),
    url(r'^article/(?P<article_id>[0-9]+)$', views.article_page, name='article_page'),
    url(r'^article/edit/$', views.article_edit_page, name='article_edit_page'),
    url(r'^article/edit/action$', views.article_edit_page_action, name='article_edit_page_action'), 
]

为action增加一个访问路径,并定义一个namespace,接下来,我们在article_edit_page.html中设置action:

<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/html">
<head>
    <meta charset="UTF-8">
    <title>编辑博客页面</title>
</head>
<form action="{% url 'blog:article_edit_page_action' %}" method="post">
    {% csrf_token %}   ##这个必须添加,否则访问时报403错误
    <label>博客标题
       <input type="text" name="title">
    </label>
    </br>
    <label>博客内容
       <input type="text" name="content">
    </label>
    </br>
    <input type="submit" value="提交">
</form>
<body>

</body>
</html>

和前面一样,为action增加响应函数的路径,这里不需要参数。csrf_token是一种网络的攻击方式,具体可以参考CSRF Token介绍与应对策略。现在需要为首页的写博客按钮增加跳转逻辑,打开index.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>首页</title>
</head>
<body>
<h3>我的博客列表:</h3>
    {% for article in articles %}
        <a href="{% url 'blog:article_page' article.id %}"> {{ article.title }} </a>
        <br/>
    {% endfor %}

    </br>
    </br>
    <a href=" {% url 'blog:article_edit_page' %} ">写博客</a>

</body>
</html>

此时刷新界面,在首页点击“写博客”即可跳转到编辑博客页面,填写内容提交会保存数据并跳转到首页面。

现在需要编写博客详情页的编辑按钮的功能,点击编辑按钮需要将这篇文章的id传递到编辑页面,在编辑页面填充该博客。既然写新博客和编辑都是跳转到同一个页面,而编辑时需要传递参数,而写博客不需要传递参数,为了兼容,我们都传递一个参数,写新博客时传递一个0,以做区别,首先,我们修改views下的编辑页面响应函数:

from django.shortcuts import render
from django.http import HttpResponse
from . import models


def index(request):
    articles = models.Article.objects.all()
    return render(request, 'index.html', {'articles': articles})


def article_page(request, article_id):
    article = models.Article.objects.get(pk=article_id)
    return render(request, 'article_page.html', {'article': article})


def article_edit_page(request, article_id):
    #str方法将参数转化为字符串,避免因传递类型差异引起的错误
    # 0代表是新增博客,否则是编辑博客,编辑博客时需要传递博客对象到页面并显示
    if str(article_id) == '0':
        return render(request, 'article_edit_page.html')
    article = models.Article.objects.get(pk=article_id)
    return render(request, 'article_edit_page.html', {'article': article})


def article_edit_page_action(request):
    title = request.POST.get('title', '默认标题')     ##get是根据参数名称从form表单页获取内容
    content = request.POST.get('content', '默认内容')
    ##保存数据
    models.Article.objects.create(title=title, content=content)
    ##数据保存完成,返回首页
    articles = models.Article.objects.all()
    return render(request, 'index.html', {'articles': articles})

这里是传递的有参数的,我们需要修改blog_urls下修改博客详情页的访问路径,增加参数

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


urlpatterns = [
    url(r'^index/', views.index),
    url(r'^article/(?P<article_id>[0-9]+)$', views.article_page, name='article_page'),
    url(r'^article/edit/(?P<article_id>[0-9]+)$', views.article_edit_page, name='article_edit_page'),  #路径中传递页码
    url(r'^article/edit/action$', views.article_edit_page_action, name='article_edit_page_action'),
]

然后修改index.html,在点击写博客时传递0

 <a href=" {% url 'blog:article_edit_page' 0 %} ">写博客</a>

修改article_page.html,为编辑按钮增加参数:

a href=" {% url 'blog:article_edit_page' article.id %} ">编辑</a>

接下来,我们修改article_page_edit.html,当从博客详情页进入时显示博客内容,从首页进入时不显示内容:

<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/html">
<head>
    <meta charset="UTF-8">
    <title>编辑博客页面</title>
</head>
<form action="{% url 'blog:article_edit_page_action' %}" method="post">
    {% csrf_token %}

    {% if article %}
       <label>博客标题
           <input type="text" name="title" value="{{ article.title }}">
        </label>
        </br>
        <label>博客内容
           <input type="text" name="content", value="{{ article.content }}">
        </label>
        </br>
        <input type="submit" value="提交">
    {% else %}
     <label>博客标题
           <input type="text" name="title">
        </label>
        </br>
        <label>博客内容
           <input type="text" name="content">
        </label>
        </br>
        <input type="submit" value="提交">
    {% endif %}
</form>
<body>

</body>
</html>

很好理解是不是,有博客就显示,没有就不显示。现在问题来了,在编辑页面,点击提交按钮到底是新增还是保存呢,现在我们需要在views中修改action的响应函数:

from django.shortcuts import render
from django.http import HttpResponse
from . import models


def index(request):
    articles = models.Article.objects.all()
    return render(request, 'index.html', {'articles': articles})


def article_page(request, article_id):
    article = models.Article.objects.get(pk=article_id)
    return render(request, 'article_page.html', {'article': article})


def article_edit_page(request, article_id):
    #str方法将参数转化为字符串,避免因传递类型差异引起的错误
    # -1代表是新增博客,否则是编辑博客,编辑博客时需要传递博客对象到页面并显示
    if str(article_id) == '0':
        return render(request, 'article_edit_page.html')
    article = models.Article.objects.get(pk=article_id)
    return render(request, 'article_edit_page.html', {'article': article})


def article_edit_page_action(request):
    title = request.POST.get('title', '默认标题')     ##get是根据参数名称从form表单页获取内容
    content = request.POST.get('content', '默认内容')
    article_id = request.POST.get('article_id_hidden', '0') ##隐藏参数,参数是在web中定义
    ##保存数据
    ##如果是0,标记新增,使用create方法,否则使用save方法
    ##新增是返回首页,编辑是返回详情页
    if str(article_id) == '0':
        models.Article.objects.create(title=title, content=content)
        ##数据保存完成,返回首页
        articles = models.Article.objects.all()
        return render(request, 'index.html', {'articles': articles})
    article = models.Article.objects.get(pk=article_id)
    article.title = title
    article.content = content
    article.save()
    return render(request, 'article_page.html', {'article': article})

然后我们修改article_page_edit.html页面,处理传递id和不传递id时提交事件的响应方法:

<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/html">
<head>
    <meta charset="UTF-8">
    <title>编辑博客页面</title>
</head>
<form action="{% url 'blog:article_edit_page_action' %}" method="post">

    {% csrf_token %}

    {% if article %}
       <input type="hidden" name="article_id_hidden"  value="{{ article.id }}">
       <label>博客标题
           <input type="text" name="title" value="{{ article.title }}">
        </label>
        </br>
        <label>博客内容
           <input type="text" name="content", value="{{ article.content }}">
        </label>
        </br>
        <input type="submit" value="提交">
    {% else %}
     <input type="hidden" name="article_id_hidden"  value="0">
     <label>博客标题
           <input type="text" name="title">
        </label>
        </br>
        <label>博客内容
           <input type="text" name="content">
        </label>
        </br>
        <input type="submit" value="提交">
    {% endif %}
</form>
<body>

</body>
</html>

运行一下程序,是不是新增和编辑功能都正常了呢,✌️!好了,整个博客小项目编写完成了。

点击下载完整的项目代码

3.小结

这个小demo非常基础,主要是讲解DTL语言的用法。从应用创建的设置,到应用中页面的显示、事件的处理,在后面的文章中我会写比较复杂的项目。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容