django的Models用法

模型是关于您的数据的单一的、确定的信息来源。它包含您存储的数据的基本字段和行为。通常,每个模型映射到单个数据库表。

基础知识:

  • 每个模型都是一个 Python 的类,这些类继承 django.db.models.Model
  • 模型类的每个属性都相当于一个数据库的字段。
  • 综上诉说,Django 给你一个自动生成访问数据库的 API;请参阅 Making queries

简单的例子

这个样例模型定义了一个 Person, 其拥有 first_name 和 last_name:

from django.db import models

class Person(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30)

firstnamelastname 是模型的字段。每个字段都被指定为class属性,每个属性映射到数据库列。

上面的Person模型会创建一个这样的数据库表:

CREATE TABLE myapp_person (
    "id" serial NOT NULL PRIMARY KEY,
    "first_name" varchar(30) NOT NULL,
    "last_name" varchar(30) NOT NULL
);

一些技术上的说明:

  • 该表的名称 “myapp_person” 是自动从某些模型元数据中派生出来,但可以被改写。有关更多详细信息,请参阅:表命名。
  • 一个 id 字段会被自动添加,但是这种行为可以被改写。请参阅:默认主键字段。
  • The CREATE TABLE SQL in this example is formatted using PostgreSQL syntax, but it's worth noting Django uses SQL tailored to the database backend specified in your settings file.

使用模型

一旦你定义了你的模型,你需要告诉Django你将会使用这些模型。通过编辑你的设置文件和改变 INSTALLED_APPS 设置来添加包含你的 models.py 的模块的名称来实现这一点。

例如,如果您的应用程序的模型存在于模块myapp.models(为应用程序创建的包结构 manage.py startapp 脚本),INSTALLED_APPS** 应该阅读部分内容:

 INSTALLED_APPS = [
    #...
    'myapp',
    #...
]

当你添加新的APP到 INSTALLED_APPS, 去报先执行manage.py migrate,有时候需要限制性 manage.py makemigrations.

字段

模型中最重要的部分——以及模型中唯一需要的部分——是它定义的数据库字段列表。字段由class属性指定。注意不要选择与模型API冲突的字段名,如clean, save 或者 delete.

例子

from django.db import models

class Musician(models.Model):
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)
    instrument = models.CharField(max_length=100)

class Album(models.Model):
     artist = models.ForeignKey(Musician, on_delete=models.CASCADE)
    name = models.CharField(max_length=100)
    release_date = models.DateField()
    num_stars = models.IntegerField()

字段类型

模型中的每个字段都应该是适当字段类的一个实例。Django使用field类类型来确定一些事情:

  • 列类型,它告诉数据库要存储什么样的数据(例如INTEGER、VARCHAR、TEXT)。
  • 默认的HTML小部件在呈现表单字段时使用(例如:<input type="text">,<select>)。
  • 在Django的管理员和自动生成的表单中使用的最小验证需求。

Django配备了数十种内置的字段类型;您可以在模型字段引用中找到完整的列表。如果Django的内置函数不奏效,您可以轻松地编写自己的字段;参见编写定制模型字段。

字段选项

每个字段都接受一组特定于字段的参数(在模型字段引用中记录)。例如,CharField(及其子类)需要一个 max_length 参数,该参数指定用于存储数据的VARCHAR 数据库字段的大小。

对于所有字段类型,也有一组通用的参数。都是可选的。它们在参考文献中得到了充分的解释,但这里有一个对最常用的解释的快速总结:

null

如果是True,Django会将空置的值存储为 NULL。默认是False

blank

如果是True,这个字段是空白的。默认是False

注意,这与null不同。null与数据库相关,而blank则是与验证相关的。如果一个字段有 blank=True ,表单验证就允许输入空值。如果一个字段有blank=False ,则需要字段。

choices

2元组的可迭代(例如,列表或元组),用作此字段的选项。如果给出了这个,则默认表单小部件将是一个选择框而不是标准文本字段,并将限制对给定选项的选择。

选择列表如下:

YEAR_IN_SCHOOL_CHOICES = (
    ('FR', 'Freshman'),
    ('SO', 'Sophomore'),
    ('JR', 'Junior'),
    ('SR', 'Senior'),
    ('GR', 'Graduate'),
)

每个元组中的第一个元素是储存在数据库中的值。第二个元素由field的form小部件显示。

给定一个模型实例,可以使用 get_FOO_display()方法访问带有选择的字段的显示值。例如:

from django.db import models

class Person(models.Model):
    SHIRT_SIZES = (
        ('S', 'Small'),
        ('M', 'Medium'),
        ('L', 'Large'),
    )
    name = models.CharField(max_length=60)
    shirt_size = models.CharField(max_length=1, choices=SHIRT_SIZES)
image.png

如果将models 加载到admin后台,显示如下:


image.png

default
字段的默认值。这可以是一个值或者一个可调用的对象。如果每次创建新对象时都将调用callable。

help_text
额外的“帮助”文本将显示在form小部件中。即使你的字段没有在表单上使用,它对文档也很有用。

 name = models.CharField(max_length=60, default=None, help_text="个人姓名")
代码
前端展示

primary_key

如果True,此字段是模型的主键

如果你没有指定你的模型中的任何字段的primarykey=True,Django会自动添加IntegerField来保存主键,所以除非你想要覆盖默认的主键行为,否则你不需要在任何字段上设置primarykey=True。更多信息,请参见自动主键字段。

主键字段是只读的。如果您将主键的值更改为现存对象,然后保存它,那么将会在旧物件旁边创建一个新物件。例如:

from django.db import models

class Fruit(models.Model):
    name = models.CharField(max_length=100, primary_key=True)

unique
如果是真的,这个字段必须在整个表中是唯一的。


自动主键字段

在默认情况下,Django提供了以下字段:

id = models.AutoField(primary_key=True)

这是一个自动递增的主键。

如果您想要指定一个定制的主键,请在您的一个字段中指定 primarykey=True。如果Django看到你已经明确地设置了字段。主键,它不会添加自动id列。

每个模型只需要一个字段来拥有primarykey=True(要么显式声明,要么自动添加)。


详细字段名称

除了和 之外ForeignKey, 每个字段类型都采用可选的第一个位置参数 - 一个详细的名称。如果没有给出详细名称,Django将使用字段的属性名称自动创建它,将下划线转换为空格。
ManyToManyFieldOneToOneField

  • 在此示例中,详细名称为:"person's first name"

first_name = models.CharField("person's first name", max_length=30)

code
前端展示
  • 在此示例中,详细名称为:"first name"

first_name = models.CharField(max_length=30)

ForeignKey, ManyToManyField and OneToOneField 都要求第一个参数是一个模型类,所以使用verbosename关键字参数:

poll = models.ForeignKey(
    Poll,
    on_delete=models.CASCADE,
    verbose_name="the related poll",
)
sites = models.ManyToManyField(Site, verbose_name="list of sites")
place = models.OneToOneField(
    Place,
    on_delete=models.CASCADE,
    verbose_name="related place",
)

公约并不是要利用**verbose_name的第一个字母。Django会自动将第一个字母大写


关联关系

显然,关系数据库的功能在于将表相互关联起来。Django提供了定义三种最常见的数据库关系类型的方法:多对一、多对多和一对一。


多对一

要定义多对一关系,请使用django.db.models.ForeignKey。您可以像使用任何其他Field类型一样使用它:将其包含为模型的类属性。

ForeignKey 需要一个位置参数:模型相关的类。

例如,如果一个“汽车”模型有一个“制造商”——也就是说,“制造商”生产多辆汽车,但每辆车都只有一个“制造商”——使用以下定义:

from django.db import models

class Manufacturer(models.Model):
    # ...
    pass

class Car(models.Model):
    manufacturer = models.ForeignKey(Manufacturer, on_delete=models.CASCADE)
    # ...

多对多

要定义多对多关系,请使用 ManyToManyField。您可以像使用任何其他Field类型一样使用它 :将其包含为模型的类属性。

ManyToManyField 需要一个位置参数:模型相关的类。

例如,如果一个“pizza”有多个“topping”的对象——也就是说,“topping”可以在多个pizza上,每个“pizza”都有多种topping——以下是你如何表示:

class Topping(models.Model):
    # ...
    pass

class Pizza(models.Model):
    # ...
    toppings = models.ManyToManyField(Topping)</pre>

多对多关系中的额外字段

当您只处理简单的多对多关系时,例如混合和匹配比萨饼和浇头,ManyToManyField您只需要一个标准 。但是,有时您可能需要将数据与两个模型之间的关系相关联。

例如,考虑应用程序跟踪音乐家所属的音乐组的情况。一个人与他们所属的团体之间存在多对多的关系,因此您可以使用aManyToManyField来表示这种关系。但是,您可能希望收集的成员资格有很多详细信息,例如此人加入该组的日期。

对于这些情况,Django允许您指定将用于管理多对多关系的模型。然后,您可以在中间模型上添加额外的字段。中间模型与ManyToManyField使用 through参数指向将充当中介的模型相关联 。对于我们的音乐家示例,代码看起来像这样:

from django.db import models

class Person(models.Model):
    name = models.CharField(max_length=128)

    def __str__(self):
        return self.name

class Group(models.Model):
    name = models.CharField(max_length=128)
    members = models.ManyToManyField(Person, through='Membership')

    def __str__(self):
        return self.name

class Membership(models.Model):
    person = models.ForeignKey(Person, on_delete=models.CASCADE)
    group = models.ForeignKey(Group, on_delete=models.CASCADE)
    date_joined = models.DateField()
    invite_reason = models.CharField(max_length=64)

设置中间模型时,您明确指定多对多关系中涉及的模型的外键。此显式声明定义了两个模型的关联方式。

中间模型有一些限制:

  • 您的中间模型必须包含一个 - 且只有一个 - 源模型的外键(这将Group在我们的示例中),或者您必须显式指定Django应该用于关系的外键ManyToManyField.through_fields。如果您有多个外键through_fields但未指定,则会引发验证错误。类似的限制适用于目标模型的外键(这将Person在我们的示例中)。
  • 对于通过中间模型与自身具有多对多关系的模型,允许同一模型的两个外键,但它们将被视为多对多关系的两个(不同)侧。如果有更多的比两个外键虽然,你还必须指定through_fields如上,或验证错误将得到提升。
  • 在使用中间模型定义从模型到自身的多对多关系时,必须使用 symmetrical=False(请参阅 模型字段引用)。

现在您已经设置了ManyToManyField使用中间模型(Membership在本例中),您已准备好开始创建一些多对多关系。您可以通过创建中间模型的实例来完成此操作:

image.png

一对一

定义一对一, use OneToOneField. 您可以像任何其他“字段”类型一样使用它:将其包含为模型的类属性。

当该对象以某种方式“扩展”另一个对象时,这在对象的主键上是最有用的。

OneToOneField 需要一个位置参数:模型相关的类。

例如,如果您正在构建“地点”数据库,您将在数据库中构建非常标准的内容,例如地址,电话号码等。然后,如果你想在这些地方建立一个餐馆数据库,而不是重复自己并在Restaurant模型中复制这些字段,你可以做Restaurant一个OneToOneFieldto Place(因为一个餐馆“是一个”地方;事实上,处理这通常使用 继承,它涉及隐式的一对一关系)。

与此同时ForeignKey,可以定义递归关系,并且可以对尚未定义的模型进行引用


跨文件的模型

将模型与另一个应用程序中的模型相关联是完全可以的。为此,请在定义模型的文件顶部导入相关模型。然后,只需在需要的地方引用其他模型类。例如:

from django.db import models
from geography.models import ZipCode

class Restaurant(models.Model):
    # ...
    zip_code = models.ForeignKey(
        ZipCode,
        on_delete=models.SET_NULL,
        blank=True,
        null=True,
    )

字段名称限制

jango对模型字段名称只有两个限制:

  1. 字段名称不能是Python保留字,因为这会导致Python语法错误。例如:

    class Example(models.Model):
       pass = models.IntegerField() # 'pass' is a reserved word!
    
  2. 由于Django的查询查找语法的工作方式,字段名称不能在一行中包含多个下划线。例如:

    class Example(models.Model):
      foo__bar = models.IntegerField() # 'foo__bar' has two underscores!
    

但是,这些限制可以解决,因为您的字段名称不一定必须与您的数据库列名称匹配。请参阅 db_column选项。

SQL保留字(例如joinwhereselect允许作为模型字段名称,因为Django会转义每个基础SQL查询中的所有数据库表名和列名。它使用特定数据库引擎的引用语法。


Meta选项

使用内部提供模型元数据,如下所示:class Meta

class Ox(models.Model):
    horn_length = models.IntegerField()

    class Meta:
        ordering = ["horn_length"]
        verbose_name_plural = "oxen"

模型元数据是“任何不是字段的东西”,例如排序选项(ordering),数据库表名(db_table)或人类可读的单数和复数名称(verbose_nameverbose_name_plural)。不需要,添加到模型是完全可选的。class Meta

Meta可以在模型选项参考中找到所有可能选项的完整列表。


模型属性

objects
模型最重要的属性是 Manager。它是为Django模型提供数据库查询操作的接口,用于 从数据库中检索实例。如果Manager未定义自定义,则默认名称为 objects。管理员只能通过模型​​类访问,而不能通过模型​​实例访问。


模型方法

在模型上定义自定义方法,以向对象添加自定义“行级”功能。虽然Manager方法旨在执行“表格范围”的事情,但模型方法应该作用于特定的模型实例。

这是将业务逻辑保存在一个地方的有价值的技术 - 模型

例如,此模型有一些自定义方法:

from django.db import models

class Person(models.Model):
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)
    birth_date = models.DateField()

    def baby_boomer_status(self):
        "Returns the person's baby-boomer status."
        import datetime
        if self.birth_date < datetime.date(1945, 8, 1):
            return "Pre-boomer"
        elif self.birth_date < datetime.date(1965, 1, 1):
            return "Baby boomer"
        else:
            return "Post-boomer"

    @property
    def full_name(self):
        "Returns the person's full name."
        return '%s %s' % (self.first_name, self.last_name)

此示例中的最后一个方法是属性

模型实例参考具有的完整列表,自动给每个模型的方法。您可以覆盖其中的大多数 - 请参阅下面的覆盖预定义模型方法 - 但有几个您几乎总是想要定义:

__str__()

Python“魔术方法”,返回任何对象的字符串表示形式。这是Python和Django在模型实例需要被强制并显示为纯字符串时将使用的内容。最值得注意的是,当您在交互式控制台或管理员中显示对象时会发生这种情况。

你总是想要定义这个方法; 默认情况下根本没有用。

get_absolute_url()

这告诉Django如何计算对象的URL。Django在其管理界面中使用它,并且只要它需要找出对象的URL。

具有唯一标识它的URL的任何对象都应定义此方法。


继承模型

模型继承在Django中与普通类继承在Python中的工作方式几乎完全相同,但也仍有遵循本页开头的内容。这意味着其基类应该继承自django.db.models.Model

您必须做出的唯一决定是您是希望父模型本身是模型(使用自己的数据库表),还是父母只是通过子模型可见的公共信息的持有者。

Django中有三种可能的继承方式。

  1. 通常,您只想使用父类来保存您不希望为每个子模型键入的信息。这个类不会被孤立使用,所以抽象基类就是你所追求的。
  2. 如果你是现有模型的子类(可能是完全来自另一个应用程序的东西),并希望每个模型都有自己的数据库表,那么 多表继承是最佳选择。
  3. 最后,如果您只想修改模型的Python级行为,而不以任何方式更改模型字段,则可以使用 代理模型

抽象基类

当您想要将一些公共信息放入许多其他模型时,抽象基类非常有用。你写你的基类,并把abstract=True 类。然后,此模型将不用于创建任何数据库表。相反,当它用作其他模型的基类时,其字段将添加到子类的字段中。

一个例子:

from django.db import models

class CommonInfo(models.Model):
    name = models.CharField(max_length=100)
    age = models.PositiveIntegerField()

    class Meta:
        abstract = True

class Student(CommonInfo):
    home_group = models.CharField(max_length=5)

Student模型将有三个领域:name,agehome_group。该CommonInfo模型不能用作普通的Django模型,因为它是一个抽象基类。它不生成数据库表或具有管理器,并且无法直接实例化或保存。

从抽象基类继承的字段可以使用其他字段或值覆盖,也可以使用删除None

对于许多用途,这种类型的模型继承将完全符合您的要求。它提供了一种在Python级别分解公共信息的方法,同时仍然只在数据库级别为每个子模型创建一个数据库表。

Meta继承

当创建抽象基类时,Django使 您在基类中声明的任何Meta内部类可用作属性。如果子类没有声明自己的Meta 类,它将继承父类的Meta。如果孩子想要扩展父类的Meta类,它可以将其子类化。例如:

from django.db import models

class CommonInfo(models.Model):
    # ...
    class Meta:
        abstract = True
        ordering = ['name']

class Student(CommonInfo):
    # ...
    class Meta(CommonInfo.Meta):
        db_table = 'student_info'

Django确实对抽象基类的Meta类进行了一次调整:在安装Meta属性之前,它设置了abstract=False。这意味着抽象基类的子项本身不会自动成为抽象类。当然,您可以创建一个继承自另一个抽象基类的抽象基类。您只需要记住abstract=True每次都明确设置。

在抽象基类的Meta类中包含一些属性是没有意义的。例如,包含db_table意味着所有子类(未指定自己的Meta)将使用相同的数据库表,这几乎肯定不是您想要的。


多表继承

Django支持的第二种模型继承是当层次结构中的每个模型都是模型本身时。每个模型对应于自己的数据库表,可以单独查询和创建。继承关系引入子模型与其每个父模型之间的链接(通过自动创建OneToOneField)。例如:

from django.db import models

class Place(models.Model):
    name = models.CharField(max_length=50)
    address = models.CharField(max_length=80)

class Restaurant(Place):
    serves_hot_dogs = models.BooleanField(default=False)
    serves_pizza = models.BooleanField(default=False)

尽管数据将驻留在不同的数据库表 PlaceRestaurant,但所有字段都将可用。所以这些都是可能的:

Place.objects.filter(name="Bob's Cafe")
Restaurant.objects.filter(name="Bob's Cafe")

如果你的a Place 也是a Restaurant,你可以使用模型名称的小写版本从 Place对象到Restaurant对象:

image.png

但是,如果p在上面的示例中不是 a Restaurant(它已直接创建为Place对象或是其他类的父级),则引用p.restaurant会引发Restaurant.DoesNotExist 异常。

自动创建OneToOneFieldRestaurant,它链接到Place看起来像这样:

place_ptr = models.OneToOneField(
    Place, on_delete=models.CASCADE,
    parent_link=True,
)

Meta和多表继承

在多表继承情况下,子类从其父类的Meta类继承是没有意义的。所有的Meta选项都已经应用于父类,并且再次应用它们通常只会导致矛盾的行为(这与基类本身不存在的抽象基类情况形成对比)。

因此,子模型无法访问其父级的Meta类。但是,有一些有限的情况,子进程从父进程继承行为:如果子进程没有指定 ordering属性或get_latest_by属性,它将从其父进程继承它们。

如果父级有一个排序而你不希望孩子有任何自然顺序,你可以明确地禁用它:

class ChildModel(ParentModel):
    # ...
    class Meta:
        # Remove parent's ordering effect
        ordering = []

代理模型

使用多表继承时,会为模型的每个子类创建一个新的数据库表。这通常是所需的行为,因为子类需要一个位置来存储基类上不存在的任何其他数据字段。但是,有时您只想更改模型的Python行为 - 可能更改默认管理器或添加新方法。

这就是代理模型继承的用途:为原始模型创建代理。您可以创建,删除和更新代理模型的实例,并且将保存所有数据,就像使用原始(非代理)模型一样。不同之处在于您可以更改代理中的默认模型排序或默认管理器等内容,而无需更改原始内容。

代理模型声明为普通模型。你通过设置类的proxy属性告诉Django它是一个代理模型。

例如,假设您要向Person模型添加方法。你可以这样做:

from django.db import models

class Person(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30)

class MyPerson(Person):
    class Meta:
        proxy = True

    def do_something(self):
        # ...
        pass

MyPerson班在同一个数据库表作为它的父工作 Person类。特别是,任何新的实例 Person 也可以通过 MyPerson,反之亦然:

image.png

你仍然可以使用一个代理模型来定义模型的默认排序方法,你也许不会想一直对“Person”进行排序,但是通常情况下用代理模型根据“姓氏”属性进行排序这很简单。:

class OrderedPerson(Person):
    class Meta:
        ordering = ["last_name"]
        proxy = True

基类限制

一个代理模型必须仅能继承一个非抽象模型类。你不能继承多个非抽象模型类,因为代理模型无法提供不同数据表的任何行间连接。一个代理模型可以继承任意数量的抽象模型类,假如他们没有定义任何的模型字段。一个代理模型也可以继承任意数量的代理模型,只需他们共享同一个非抽象父类


模型代理管理器

如果未在代理模型上指定任何模型管理器,它将从其模型父项继承管理器。如果您在代理模型上定义管理器,它将成为默认管理器,尽管在父类上定义的任何管理器仍然可用。

继续上面的示例,您可以更改查询Person模型时使用的默认管理器,如下所示:

from django.db import models

class NewManager(models.Manager):
    # ...
    pass

class MyPerson(Person):
    objects = NewManager()

    class Meta:
        proxy = True

如果要在不更换现有默认值的情况下向代理添加新管理器,可以使用自定义管理器文档中描述的技术:创建包含新管理器的基类,并在主基类之后继承:

# Create an abstract class for the new manager.
class ExtraManagers(models.Model):
    secondary = NewManager()

    class Meta:
        abstract = True

class MyPerson(Person, ExtraManagers):
    class Meta:
        proxy = True

多重继承

正如Python的子类化一样,Django模型可以从多个父模型继承。请记住,正常的Python名称解析规则适用。特定名称(例如Meta)出现的第一个基类将是使用的基类; 例如,这意味着如果多个父类包含一个Meta类,则只会使用第一个类,而将忽略所有其他类。

通常,您不需要从多个父级继承。这有用的主要用例是“混入”类:向每个继承混合的类添加特定的额外字段或方法。尽量使您的继承层次结构尽可能简单明了,这样您就不必费力去找出特定信息来自哪里。

请注意,从具有公共id主键字段的多个模型继承将引发错误。要正确使用多重继承,可以AutoField在基本模型中使用explici

class Article(models.Model):
    article_id = models.AutoField(primary_key=True)
    ...

class Book(models.Model):
    book_id = models.AutoField(primary_key=True)
    ...

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

推荐阅读更多精彩内容