Django之Form组件详解、图片上传及定制

Django的Form功能

●生成HTML标签

●验证用户数据(显示错误信息)

●HTML Form提交保留上次提交数据

●初始化页面显示内容

Django form 流程

1、创建类,继承form.Form

2、页面根据类的对象自动创建html标签

3、提交,request.POST

      封装到类的对象里,obj=UserInfo(request.POST)

4、用户输入是否合法

    obj.is_valid()

5、全部合法,获取全部内容

    obj.clean()

6、只有有不合法

    obj.errors

1、创建Form类

fromdjango.formsimportForm

fromdjango.formsimportwidgets

fromdjango.formsimportfields

classMyForm(Form):

    user = fields.CharField(

widget=widgets.TextInput(attrs={'id':'i1','class':'c1'})

    )

    gender = fields.ChoiceField(

choices=((1,'男'), (2,'女'),),

initial=2,

        widget=widgets.RadioSelect

    )

    city = fields.CharField(

initial=2,

widget=widgets.Select(choices=((1,'上海'),(2,'北京'),))

    )

    pwd = fields.CharField(

widget=widgets.PasswordInput(attrs={'class':'c1'}, render_value=True)

    )

2、View函数处理

fromdjango.shortcutsimportrender, redirect

from.formsimportMyForm

defindex(request):

ifrequest.method =="GET":

        obj = MyForm()

returnrender(request,'index.html', {'form': obj})

elifrequest.method =="POST":

        obj = MyForm(request.POST, request.FILES)

ifobj.is_valid():

            values = obj.clean()

            print(values)

else:

            errors = obj.errors

            print(errors)

returnrender(request,'index.html', {'form': obj})

else:

returnredirect('http://www.google.com')

3、生成HTML

<form action="/" method="POST" enctype="multipart/form-data">

    <p>{{ form.user }} {{ form.user.errors }}</p>

    <p>{{ form.gender }} {{ form.gender.errors }}</p>

    <p>{{ form.city }} {{ form.city.errors }}</p>

    <p>{{ form.pwd }} {{ form.pwd.errors }}</p>

    <input type="submit"/>

</form>

<form method="POST" enctype="multipart/form-data">

        {% csrf_token %}       

            {{ form.xxoo.label }}

            {{ form.xxoo.id_for_label }}

            {{ form.xxoo.label_tag }}

            {{ form.xxoo.errors }}

            <p>{{ form.user }} {{ form.user.errors }}</p>

            <input type="submit" />

    </form>

Form类

创建Form类时,主要涉及到 【字段】 和 【插件】,字段用于对用户请求数据的验证,插件用于自动生成HTML;

1、Django内置字段如下:

Field

required=True,              是否允许为空

widget=None,                HTML插件

label=None,                  用于生成Label标签或显示内容

initial=None,                初始值

help_text='',                帮助信息(在标签旁边显示)

error_messages=None,        错误信息 {'required':'不能为空','invalid':'格式错误'}

show_hidden_initial=False,  是否在当前插件后面再加一个隐藏的且具有默认值的插件(可用于检验两次输入是否一直)

    validators=[],              自定义验证规则

localize=False,              是否支持本地化

disabled=False,              是否可以编辑

label_suffix=NoneLabel内容后缀

CharField(Field)

max_length=None,            最大长度

min_length=None,            最小长度

strip=True是否移除用户输入空白

IntegerField(Field)

max_value=None,              最大值

min_value=None,              最小值

FloatField(IntegerField)

    ...

DecimalField(IntegerField)

max_value=None,              最大值

min_value=None,              最小值

max_digits=None,            总长度

decimal_places=None,        小数位长度

BaseTemporalField(Field)

input_formats=None时间格式化

DateField(BaseTemporalField)    格式:2015-09-01

TimeField(BaseTemporalField)    格式:11:12

DateTimeField(BaseTemporalField)格式:2015-09-0111:12

DurationField(Field)            时间间隔:%d %H:%M:%S.%f

    ...

RegexField(CharField)

    regex,                      自定制正则表达式

max_length=None,            最大长度

min_length=None,            最小长度

error_message=None,        忽略,错误信息使用 error_messages={'invalid':'...'}

EmailField(CharField)     

    ...

FileField(Field)

allow_empty_file=False是否允许空文件

ImageField(FileField)          ...

    注:需要PIL模块,pip3 install Pillow

    以上两个字典使用时,需要注意两点:

- form表单中 enctype="multipart/form-data"

        - view函数中 obj = MyForm(request.POST, request.FILES)

URLField(Field)

    ...

BooleanField(Field) 

    ...

NullBooleanField(BooleanField)

    ...

ChoiceField(Field)

    ...

choices=(),                选项,如:choices = ((0,'上海'),(1,'北京'),)

required=True,            是否必填

widget=None,              插件,默认select插件

label=None,                Label内容

initial=None,              初始值

help_text='',              帮助提示

ModelChoiceField(ChoiceField)

    ...                        django.forms.models.ModelChoiceField

queryset,# 查询数据库中的数据

empty_label="---------",# 默认空显示内容

to_field_name=None,# HTML中value的值对应的字段

limit_choices_to=None# ModelForm中对queryset二次筛选   

ModelMultipleChoiceField(ModelChoiceField)

    ...                        django.forms.models.ModelMultipleChoiceField   

TypedChoiceField(ChoiceField)

coerce =lambdaval: val  对选中的值进行一次转换

empty_value=''空值的默认值

MultipleChoiceField(ChoiceField)

    ...

TypedMultipleChoiceField(MultipleChoiceField)

coerce =lambdaval: val  对选中的每一个值进行一次转换

empty_value=''空值的默认值

ComboField(Field)

fields=()                  使用多个验证,如下:即验证最大长度20,又验证邮箱格式

fields.ComboField(fields=[fields.CharField(max_length=20), fields.EmailField(),])

MultiValueField(Field)

    PS: 抽象类,子类中可以实现聚合多个字典去匹配一个值,要配合MultiWidget使用

SplitDateTimeField(MultiValueField)

input_date_formats=None,  格式列表:['%Y--%m--%d','%m%d/%Y','%m/%d/%y']

input_time_formats=None格式列表:['%H:%M:%S','%H:%M:%S.%f','%H:%M']

FilePathField(ChoiceField)    文件选项,目录下文件显示在页面中

    path,                      文件夹路径

match=None,                正则匹配

recursive=False,          递归下面的文件夹

allow_files=True,          允许文件

allow_folders=False,      允许文件夹

required=True,

widget=None,

label=None,

initial=None,

help_text=''

GenericIPAddressField

protocol='both',          both,ipv4,ipv6支持的IP格式

unpack_ipv4=False解析ipv4地址,如果是::ffff:192.0.2.1时候,可解析为192.0.2.1, PS:protocol必须为both才能启用

SlugField(CharField)          数字,字母,下划线,减号(连字符)

    ...

UUIDField(CharField)          uuid类型

    ...

注:UUID是根据MAC以及当前时间等创建的不重复的随机字符串

>>>importuuid

# make a UUID based on the host ID and current time

>>> uuid.uuid1()# doctest: +SKIP

UUID('a8098c1a-f86e-11da-bd1a-00112444be1e')

# make a UUID using an MD5 hash of a namespace UUID and a name

>>> uuid.uuid3(uuid.NAMESPACE_DNS,'python.org')

UUID('6fa459ea-ee8a-3ca4-894e-db77e160355e')

# make a random UUID

>>> uuid.uuid4()# doctest: +SKIP

UUID('16fd2706-8baf-433b-82eb-8c7fada847da')

# make a UUID using a SHA-1 hash of a namespace UUID and a name

>>> uuid.uuid5(uuid.NAMESPACE_DNS,'python.org')

UUID('886313e1-3b8a-5372-9b90-0c9aee199e5d')

# make a UUID from a string of hex digits (braces and hyphens ignored)

>>> x = uuid.UUID('{00010203-0405-0607-0809-0a0b0c0d0e0f}')

# convert a UUID to a string of hex digits in standard form

    >>> str(x)

'00010203-0405-0607-0809-0a0b0c0d0e0f'

# get the raw 16 bytes of the UUID

    >>> x.bytes

b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f'

# make a UUID from a 16-byte string

    >>> uuid.UUID(bytes=x.bytes)

UUID('00010203-0405-0607-0809-0a0b0c0d0e0f')

2、Django内置插件:

TextInput(Input)

NumberInput(TextInput)

EmailInput(TextInput)

URLInput(TextInput)

PasswordInput(TextInput)

HiddenInput(TextInput)

Textarea(Widget)

DateInput(DateTimeBaseInput)

DateTimeInput(DateTimeBaseInput)

TimeInput(DateTimeBaseInput)

CheckboxInput

Select

NullBooleanSelect

SelectMultiple

RadioSelect

CheckboxSelectMultiple

FileInput

ClearableFileInput

MultipleHiddenInput

SplitDateTimeWidget

SplitHiddenDateTimeWidget

SelectDateWidget

常用选择插件

# 单radio,值为字符串

# user = fields.CharField(

#    initial=2,

#    widget=widgets.RadioSelect(choices=((1,'上海'),(2,'北京'),))

# )

# 单radio,值为字符串

# user = fields.ChoiceField(

#    choices=((1, '上海'), (2, '北京'),),

#    initial=2,

#    widget=widgets.RadioSelect

# )

# 单select,值为字符串

# user = fields.CharField(

#    initial=2,

#    widget=widgets.Select(choices=((1,'上海'),(2,'北京'),))

# )

# 单select,值为字符串

# user = fields.ChoiceField(

#    choices=((1, '上海'), (2, '北京'),),

#    initial=2,

#    widget=widgets.Select

# )

# 多选select,值为列表

# user = fields.MultipleChoiceField(

#    choices=((1,'上海'),(2,'北京'),),

#    initial=[1,],

#    widget=widgets.SelectMultiple

# )


# 单checkbox

# user = fields.CharField(

#    widget=widgets.CheckboxInput()

# )

# 多选checkbox,值为列表

# user = fields.MultipleChoiceField(

#    initial=[2, ],

#    choices=((1, '上海'), (2, '北京'),),

#    widget=widgets.CheckboxSelectMultiple

# )

在使用选择标签时,需要注意choices的选项可以从数据库中获取,但是由于是静态字段 ***获取的值无法实时更新***,那么需要自定义构造方法从而达到此目的。

方式一:

fromdjango.formsimportForm

fromdjango.formsimportwidgets

fromdjango.formsimportfields

fromdjango.core.validatorsimportRegexValidator

classMyForm(Form):

    user = fields.ChoiceField(

# choices=((1, '上海'), (2, '北京'),),

initial=2,

        widget=widgets.Select

    )

def__init__(self, *args, **kwargs):

        super(MyForm,self).__init__(*args, **kwargs)

# self.fields['user'].widget.choices = ((1, '上海'), (2, '北京'),)

# 或

self.fields['user'].widget.choices = models.Classes.objects.all().value_list('id','caption')

方式二:

使用django提供的ModelChoiceField和ModelMultipleChoiceField字段来实现

fromdjangoimportforms

fromdjango.formsimportfields

fromdjango.formsimportwidgets

fromdjango.formsimportmodelsasform_model

fromdjango.core.exceptionsimportValidationError

fromdjango.core.validatorsimportRegexValidator

classFInfo(forms.Form):

    authors = form_model.ModelMultipleChoiceField(queryset=models.NNewType.objects.all())

# authors = form_model.ModelChoiceField(queryset=models.NNewType.objects.all())

自定义验证规则

方式一:

from django.forms import Form

from django.forms import widgets

from django.forms import fields

from django.core.validators import RegexValidator

class MyForm(Form):

    user = fields.CharField(

        validators=[RegexValidator(r'^[0-9]+$', '请输入数字'), RegexValidator(r'^159[0-9]+$', '数字必须以159开头')],

    )

方式二:

import re

from django.forms import Form

from django.forms import widgets

from django.forms import fields

from django.core.exceptions import ValidationError

# 自定义验证规则

def mobile_validate(value):

    mobile_re = re.compile(r'^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$')

    if not mobile_re.match(value):

        raise ValidationError('手机号码格式错误')

class PublishForm(Form):

    title = fields.CharField(max_length=20,

                            min_length=5,

                            error_messages={'required': '标题不能为空',

                                            'min_length': '标题最少为5个字符',

                                            'max_length': '标题最多为20个字符'},

                            widget=widgets.TextInput(attrs={'class': "form-control",

                                                          'placeholder': '标题5-20个字符'}))

    # 使用自定义验证规则

    phone = fields.CharField(validators=[mobile_validate, ],

                            error_messages={'required': '手机不能为空'},

                            widget=widgets.TextInput(attrs={'class': "form-control",

                                                          'placeholder': u'手机号码'}))

    email = fields.EmailField(required=False,

                            error_messages={'required': u'邮箱不能为空','invalid': u'邮箱格式错误'},

                            widget=widgets.TextInput(attrs={'class': "form-control", 'placeholder': u'邮箱'}))

方法三:自定义方法

from django import forms

    from django.forms import fields

    from django.forms import widgets

    from django.core.exceptions import ValidationError

    from django.core.validators import RegexValidator

    class FInfo(forms.Form):

        username = fields.CharField(max_length=5,

                                    validators=[RegexValidator(r'^[0-9]+$', 'Enter a valid extension.', 'invalid')], )

        email = fields.EmailField()

        def clean_username(self):

            """

            Form中字段中定义的格式匹配完之后,执行此方法进行验证

            :return:

            """

            value = self.cleaned_data['username']

            if "666" in value:

                raise ValidationError('666已经被玩烂了...', 'invalid')

            return value

方式四:同时生成多个标签进行验证

from django.forms import Form

from django.forms import widgets

from django.forms import fields

from django.core.validators import RegexValidator

############## 自定义字段 ##############

class PhoneField(fields.MultiValueField):

    def __init__(self, *args, **kwargs):

        # Define one message for all fields.

        error_messages = {

            'incomplete': 'Enter a country calling code and a phone number.',

        }

        # Or define a different message for each field.

        f = (

            fields.CharField(

                error_messages={'incomplete': 'Enter a country calling code.'},

                validators=[

                    RegexValidator(r'^[0-9]+$', 'Enter a valid country calling code.'),

                ],

            ),

            fields.CharField(

                error_messages={'incomplete': 'Enter a phone number.'},

                validators=[RegexValidator(r'^[0-9]+$', 'Enter a valid phone number.')],

            ),

            fields.CharField(

                validators=[RegexValidator(r'^[0-9]+$', 'Enter a valid extension.')],

                required=False,

            ),

        )

        super(PhoneField, self).__init__(error_messages=error_messages, fields=f, require_all_fields=False, *args,

                                        **kwargs)

    def compress(self, data_list):

        """

        当用户验证都通过后,该值返回给用户

        :param data_list:

        :return:

        """

        return data_list

############## 自定义插件 ##############

class SplitPhoneWidget(widgets.MultiWidget):

    def __init__(self):

        ws = (

            widgets.TextInput(),

            widgets.TextInput(),

            widgets.TextInput(),

        )

        super(SplitPhoneWidget, self).__init__(ws)

    def decompress(self, value):

        """

        处理初始值,当初始值initial不是列表时,调用该方法

        :param value:

        :return:

        """

        if value:

            return value.split(',')

        return [None, None, None]

初始化数据

在Web应用程序中开发编写功能时,时常用到获取数据库中的数据并将值初始化在HTML中的标签上。

1、Form

from django.forms import Form

from django.forms import widgets

from django.forms import fields

from django.core.validators import RegexValidator 

class MyForm(Form):

    user = fields.CharField()

    city = fields.ChoiceField(

        choices=((1, '上海'), (2, '北京'),),

        widget=widgets.Select

    )

2、Views

from django.shortcuts import render, redirect

from .forms import MyForm

def index(request):

    if request.method == "GET":

        values = {'user': 'root', 'city': 2}

        obj = MyForm(values)

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

    elif request.method == "POST":

        return redirect('http://www.google.com')

    else:

        return redirect('http://www.google.com')

3、HTML

    {% csrf_token %}

{{ form.user }} {{ form.user.errors }}

{{ form.city }} {{ form.city.errors }}

基于form的django图片上传

第一种,直接上传

views

classTestimgForm(forms.Form):

    title = fields.CharField()

    img = fields.FileField()

deftestimg(request):

importos,time

ifrequest.method =='GET':

        img = TestimgForm()

returnrender(request,'backend/testimg.html',{'img':img})

else:

        obj = TestimgForm(request.POST, request.FILES)

ifobj.is_valid():

img = request.FILES.get('img')

time = time.strftime('%Y%m%d%H%M%S')

ext = os.path.splitext(img.name)[1]

file_path = os.path.join('upload/article',time+ext)

#将图片重命名

f = open(file_path,'wb')

forlineinimgs.chunks():

            f.write(line)

            f.close()

returnHttpResponse('上传成功')

第二种,写入数据库

html

<!DOCTYPE html>

<head>

    <title>Title</title>

</head>

<body>

    {% csrf_token %}

    {{ img }}

</form>

</body>

</html>

views

classTestimgForm(forms.Form):

    title = fields.CharField()

    img = fields.FileField()

deftestimg(request):

importos,time

ifrequest.method =='GET':

        img = TestimgForm()

returnrender(request,'backend/testimg.html',{'img':img})

else:

        obj = TestimgForm(request.POST, request.FILES)

ifobj.is_valid():

title = obj.cleaned_data['title']

img = obj.cleaned_data['img']

time = time.strftime('%Y%m%d%H%M%S')

ext = os.path.splitext(img.name)[1]

img.name = time + ext

            Imgtest.objects.create(title=title,img=img)

returnHttpResponse('上传成功')

models.py

classImgtest(models.Model):title = models.CharField(verbose_name='标题',max_length=32,)    img = models.ImageField(verbose_name='缩略图',upload_to="./article/",                            help_text="大小200*200,不超过200k",                            default="/upload/article/common.jpg")

完整代码

classTestimgForm(forms.Form):

    title = fields.CharField()

    img = fields.FileField()

deftestimg(request):

importos,time

ifrequest.method =='GET':

        img = TestimgForm()

returnrender(request,'backend/testimg.html',{'img':img})

else:

        obj = TestimgForm(request.POST, request.FILES)

ifobj.is_valid():

#(request.FILES['file'])

# title = request.FILES.get('title')

# img = request.FILES.get('img')

title = obj.cleaned_data['title']

img = obj.cleaned_data['img']

time = time.strftime('%Y%m%d%H%M%S')

ext = os.path.splitext(img.name)[1]

            img.name = time + ext

# Imgtest.objects.create(title=title,img=img)

# img是对象(文件大小,文件名称,文件内容。。。)

# file_path = os.path.join('upload/article',time+ext)

file_path = os.path.join('upload/article', img.name)

f = open(file_path,'wb')

forlineinimg.chunks():

                f.write(line)

            f.close()

returnHttpResponse('...')

Form定制化

定制错误信息

mail = forms.EmailField(error_messages={'required':u'邮箱不能为空'})

定制错误规则

mobile = forms.CharField(validators=[mobile_validate,],

                        error_messages={'required':u'手机不能为空'})

from django.shortcuts import render

from django import forms

import re

from django.core.exceptions import ValidationError

def mobile_validate(value):

    mobile_re = re.compile(r'^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$')

    if not mobile_re.match(value):

        raise ValidationError('手机号码格式错误')


class UserInfo(forms.Form):

    email = forms.EmailField(error_messages={'required':u'邮箱不能为空'})

    host = forms.CharField(error_messages={'required':u'主机不能为空'})

    port = forms.CharField(error_messages={'required':u'端口不能为空'})

    mobile = forms.CharField(validators=[mobile_validate,], #定义错误规则函数

      error_messages={'required':u'手机不能为空'},

      widget=forms.TextInput(attrs={'class':'form-control', #定义class

      'placeholder':u'请输入手机号'}))

   beizhu = forms.CharField(required=False, #备注允许为空

      widget=forms.Textarea(attrs={'class':'form-control', #定义为多行输入框

      'placeholder':u'请输入备注'}))

   user_type_choice = (

          (0,u'普通用户'),

       (1,u'高级用户'),

      )

   user_type = forms.IntegerField(widget=forms.widgets.Select(choices=user_type_choice,attrs={'class':'form-control'}))

保存用户输入内容

obj = AccountForm.LoginForm(request.POST)

Form表单验证以及错误信息

错误信息格式:

普通格式:

from django.shortcuts import render,HttpResponse

from web.forms import account as AccountForm


def login(request):

    obj = AccountForm.LoginForm(request.POST)

    if request.method == 'POST':

        if obj.is_valid():

            all_data = obj.clean()

        else:

            #用于Form表单提交

error = obj.errors

            #print error['username'][0]

            #print error['password'][0]

       return render(request, 'account/login.html',{'obj':obj,'error':error})


    return render(request, 'account/login.html',{'obj':obj})

 创建一个simple_tag,使其输 error['username'][0]

{% load xx %}

<!DOCTYPE html>

<html lang="en">

<head>

    <meta charset="UTF-8">

    <title></title>

</head>

<body>

    <form action="/login/" method="post">

        <p>{{ obj.username }}

            {% error_msg error.username %}

        </p>

        <p>{{ obj.password }}

            {% error_msg error.password %}

        </p>

        <input type="submit" value="提交">

    </form>

JSON格式

def login(request):

    obj = AccountForm.LoginForm(request.POST)

    if request.method == 'POST':

        if obj.is_valid():

            all_data = obj.clean()

        else:

            #用于Ajax

error = obj.errors.as_json()

            #print error

return HttpResponse(error)

        return render(request, 'account/login.html',{'obj':obj,'error':error})

    return render(request, 'account/login.html',{'obj':obj})

Form生成select标签

静态select

动态select

当增加数据库数据时

不会更新,除非关闭程序,重新载入才会更新

解决方法:利用面向对象类的静态字段

from django import forms

import json


class ImportForm(forms.Form):

    #静态select

HOST_TYPE_LIST = (

        (0,'物理机'),

(1,'虚拟机'),

)

    host_type = forms.IntegerField(

        widget=forms.Select(choices=HOST_TYPE_LIST)

    )

    hostname = forms.CharField()


    #动态select

    # admin_dic = ((1,'yangmv'),(1,"bob"),)

    # w_obj = open('db_admin','w')

    # w_obj.write(json.dumps(admin_dic))

    # w_obj.close()

f_obj = open('db_admin','r')

    data = f_obj.read()

    data_tuple = json.loads(data)

    admin = forms.IntegerField(

        widget=forms.Select(choices=data_tuple)

    )


    def __init__(self,*args,**kwargs):

        super(ImportForm,self).__init__(*args,**kwargs)

        tmp = open('db_admin')

        data = tmp.read()

        data_tuple = json.loads(data)

        self.fields['admin'].widget.choices = data_tuple

  再次增加数据库数据,直接刷新页面即可读取到新数据

优化后代码

from django import forms

import json


class ImportForm(forms.Form):

    admin = forms.IntegerField(widget=forms.Select())

    def __init__(self,*args,**kwargs):

        super(ImportForm,self).__init__(*args,**kwargs)

        tmp = open('db_admin')

        data = tmp.read()

        data_tuple = json.loads(data)

        self.fields['admin'].widget.choices = data_tuple

使用models获取select数据

class Select(models.Model):

    username = models.CharField(max_length=16)

    password = models.CharField(max_length=32)

<body>

    <form action="/home/">

        <p>{{ obj.admin }}</p>

    </form>

</body>

def home(request):

    obj = HomeForm.ImportForm()

    return render(request, 'home/home.html',{'obj':obj})

models.Select.objects.all().values_list('id','username')

https://www.cnblogs.com/yangmv/p/5327427.html

http://www.liujiangblog.com/course/django/152

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

推荐阅读更多精彩内容