Django丨模版层 - 1. 模型和字段
模型和字段
一个模型(model
)就是一个单独的、确定的数据的信息源,包含了数据的字段和操作方法。通常,每个模型映射为一张数据库中的表。
基本的原则,如下:
- 每个模型在Django中的存在形式为一个Python类;
- 每个类都是
django.db.models.Model
的子类; - 模型(类)的每个字段(属性)代表数据表的某一列;
- Django自动为你生成访问数据库的API;
1. 简单示例
下面的模型定义了一个“人”,它具有first_name
和last_name
字段:
1 | from django.db import models |
每一个字段都是一个类属性,每个类属性表示数据表中的一个列。
上面的代码,相当于下面的原生SQL语句:
1 | CREATE TABLE myapp_person ( |
注意:
- 表名
myapp_person
由Django自动生成,默认格式为“项目名称+下划线+小写类名”,你可以重写这个规则。- Django会自动创建自增主键
id
,当然,你也可以自己指定主键。- 上面的SQL语句基于
PostgreSQL
语法。
通常,我们会将模型编写在其所属app
下的models.py
文件中,没有特别需求时,请坚持这个原则,不要自己给自己添加麻烦。
创建了模型之后,在使用它之前,你需要先在settings
文件中的INSTALLED_APPS
处,注册models.py
文件所在的myapp
。看清楚了,是注册app
,不是模型,也不是models.py
。如果你以前写过模型,可能已经做过这一步工作,可跳过。
1 | INSTALLED_APPS = [ |
当你每次对模型进行 增、删、改 时,请务必执行命令python manage.py migrate
,让操作实际应用到数据库上。这里可以选择在执行migrate
之前,先执行python manage.py makemigrations
让修改动作保存到记录文件中,方便github等工具的使用。
2. 模型的属性
每个模型都可以有很多属性,其中有Django内置的,也可以有你自定义的。
模型当中最重要的属性是Manager
管理器。它是 Django 模型和数据库查询操作之间的API接口,用于从数据库当中获取数据实例。如果没有指定自定义的 Manager
,那么它默认名称是 objects
,这是Django自动为我们提供和生成的。Manager
只能通过模型类来访问,不能通过模型实例来访问,也就是说,只能Person.objects
,不可以jack.objects
。
模型还有一个不为人知的隐藏属性_state
。
_state
属性指向一个ModelState
类实例,它持续跟踪着模型实例的生命周期。
_state
自己又有2个属性:adding
和db
adding
:一个标识符,如果当前的模型实例还没有保存到数据库内,则为True
,否则为False
db
:一个字符串指向某个数据库,当前模型实例是从该数据库中读取出来的。
所以:
- 对于一个新创建的模型实例:
adding=True
并且db=None
- 对于从某个数据库中读取出来的模型实例:
adding=False
并且db='数据库名'
1 | >>> blog = Blog.create('mary', 'ss') |
3. 模型方法
模型的方法其实就是Python的实例方法。Django内置了一些,我们也可以自定义一些。
在模型中添加自定义方法会给你的模型提供自定义的“行级”数据操作能力,也就是说每个模型的实例都可以调用模型方法。与之对应的是类 Manager
的方法提供的是“表级”的数据操作。
在后面的章节有对Django内置API方法的详细介绍。
建议:如果你有一段需要针对每个模型实例都有效的业务代码,应该把它们抽象成为一个函数,放到模型中成为模型方法,而不是在大量视图中重复编写这段代码,或者在视图中抽象成一个函数。
下面的例子展示了如何自定义模型方法:
1 | class Person(models.Model): |
baby_boomer_status
作为一个自定义的模型方法,可以被任何Person
的实例调用,进行生日日期判断full_name
模型方法被Python的属性装饰器转换成了一个类属性
具体使用操作:
1 | >>>jack = Person.objects.get(pk=1) |
Django内置了一些模型方法,有些我们直接使用即可,有些会进行自定义重写:
__str__()
: 这个其实是Python的魔法方法,用于返回实例对象的打印字符串。为了让显示的内容更直观更易懂,我们往往自定义这个方法:
1 | class Person(models.Model): |
get_absolute_url()
: 这个方法是返回每个模型实例的相应的访问url。__hash__()
:- 实际上,Django在内部还为
models.Model
实现了__hash__()
魔法方法,给模型实例提供唯一的哈希值。 - 这个方法的核心是
hash(obj.pk)
,通过模型主键的值,使用内置的hash
方法生成哈希值。如果实例还未保存,没有主键值,显然会发生错误。哈希值一旦生成就不允许修改。
- 实际上,Django在内部还为
4. 模型字段fields
字段是模型中最重要的内容之一,也是唯一必须的部分。字段在Python中表现为一个类属性,体现了数据表中的一个列。请不要使用clean
、save
、delete
等Django内置的模型API名字,防止命名冲突。
下面是一个展示,注意字段的写法:
1 | from django.db import models |
4.1 字段命名约束
Django不允许下面三种字段名:
与Python关键字冲突。这会导致语法错误。例如:
1
2class Example(models.Model):
pass = models.IntegerField() # 'pass'是Python保留字!字段名中不能有两个以上下划线在一起,因为两个下划线是Django的查询语法。例如:
1
2class Example(models.Model):
foo__bar = models.IntegerField() # 'foo__bar' 有两个下划线在一起!字段名不能以下划线结尾,原因同上。
由于你可以自定义表名、列名,上面的规则可能被绕开,但是请养成良好的习惯,一定不要那么起名。
5. 模型字段类型
下篇再出