Django学习笔记基于刘江Django2.0教程
ORM(关系映射模型)系统:将一个Python的对象映射为数据库中的一张关系表。
它将SQL装起来,程序员不再需要关心数据库的具体操作,只需要专注于自己本身代码和业务逻辑的实现。
例如:整体的实现过程就是:Python代码,通过ORM转换成SQL语句,再通过pymysql(mysql)去实际操作数据库。
Django的ORM系统体现在框架内就是模型层。
想要理解模型层的概念,关键在于理解用Python代码的方式来定义数据库表的做法!一个Python的类,就是一个模型,代表数据库中的一张数据表!Django奉行Python优先的原则,一切基于Python代码的交流,完全封装SQL内部细节。
一、模型与字段
(1)模型
一个模型(model)就是一个单独的、确定的数据的信息源,包含了数据的字段和操作方法。
通常,每个模型映射为一张数据库中的表。
基本的原则如下:
- 每个模型在Django中的存在形式为一个Python类
- 每个模型都是django.db.models.Model的子类
- 模型的每个字段(属性)代表数据表的某一列
- Django将自动为你生成数据库访问API
简单示例:
下面的模型定义了一个“人”,它具有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)
上面模型相当于下面SQL代码:
CREATE TABLE myapp_person (
"id" serial NOT NULL PRIMARY KEY,
"first_name" varchar(30) NOT NULL,
"last_name" varchar(30) NOT NULL
);
注意:
1.表名myapp_person由Django自动生成,默认格式为“项目名称+下划线+小写类名”,你可以重写这个规则。
2.Django默认自动创建自增主键id,当然,你也可以自己指定主键。
3.上面的SQL语句基于PostgreSQL语法。
注意:创建了模型之后,在使用它之前,你需要先在settings文件中的INSTALLED_APPS
处,注册models.py
文件所在的myapp
。
注意:当你每次对模型进行增、删、修改时,请务必执行命令python manage.py migrate
,让操作实际应用到数据库上。这里可以选择在执行migrate之前,先执行python manage.py makemigrations
让修改动作保存到记录文件中,方便github等工具的使用。
(2)模型字段 fields
命名规则:
字段命名不能使用clean、save、delete等Django内置的模型API名字,防止命名冲突。
Django不允许下面两种字段名:
-
与Python关键字冲突。这会导致语法错误。例如:
class Example(models.Model): pass = models.IntegerField() # 'pass'是Python保留字!
-
字段名中不能有两个以上下划线在一起,因为两个下划线是Django的查询语法。例如:
class Example(models.Model): foo__bar = models.IntegerField() # 'foo__bar' 有两个下划线在一起!
字段类型的作用:
- 决定数据库中对应列的数据类型(例如:INTEGER, VARCHAR, TEXT)
- HTML中对应的表单标签的类型,例如
<input type=“text” />
- 在admin后台和自动生成的表单中最小的数据验证需求
Django所有内置的字段类型,但不包括关系字段类型(字段名采用驼峰命名法):
AutoField | 一个自动增加的整数类型字段。通常你不需要自己编写它,Django会自动帮你添加字段:
Django在一个模型中只允许有一个自增字段,并且该字段必须为主键! |
BigAutoField | (1.10新增) 64位整数类型自增字段,数字范围更大,从1到9223372036854775807 |
BigIntegerFeild | 64位整数字段(看清楚,非自增) 类似 IntegerField ,-9223372036854775808 到9223372036854775807。 在Django的模板表单里体现为一个textinput标签。 |
BinaryField | 二进制数据类型。使用受限,少用。 |
BooleanField | 布尔值类型。默认值是None。 在HTML表单中体现为CheckboxInput标签。如果要接收null值,请使用NullBooleanField。 |
CharField | 字符串类型。必须接收一个max_length参数,表示字符串长度不能超过该值。 默认的表单标签是input text。最常用的filed,没有之一! |
CommaSeparatedIntegerField | 逗号分隔的整数类型。必须接收一个max_length参数。 常用于表示较大的金额数目,例如1,000,000元。 |
DateField |
日期类型。一个Python中的datetime.date的实例。在HTML中表现为TextInput标签。在admin后台中,Django会帮你自动添加一个JS的日历表和一个“Today”快捷方式,以及附加的日期合法性验证。 两个重要参数:(参数互斥,不能共存)
设置上面两个参数就相当于给field添加了 |
DateTimeField | 日期时间类型。Python的datetime.datetime的实例。 与DateField相比就是多了小时、分和秒的显示,其它功能、参数、用法、默认值等等都一样。 |
DecimalField | 固定精度的十进制小数。相当于Python的Decimal实例,必须提供两个指定的参数
当 例子:储存最大不超过999,带有2位小数位精度的数, 定义如下: |
DurationField | 持续时间类型。存储一定期间的时间长度。类似Python中的timedelta。在不同的数据库实现中有不同的表示方法。常用于进行时间之间的加减运算。但是小心了,这里有坑,PostgreSQL等数据库之间有兼容性问题! |
EmailField | 邮箱类型,默认max_length最大长度254位。 使用这个字段的好处是,可以使用Django内置的EmailValidator进行邮箱地址合法性验证。 |
FileField | 上传文件类型 class FileField(upload_to=None, max_length=100, **options) ,后面单独介绍。 |
FilePathField | 文件路径类型,后面单独介绍 |
FloatField | 浮点数类型,参考整数类型 |
ImageField | 图像类型,后面单独介绍 |
IntegerField | 整数类型,最常用的字段之一。 取值范围-2147483648到2147483647。在HTML中表现为NumberInput标签。 |
GenericIPAddressField | class GenericIPAddressField(protocol='both', unpack_ipv4=False, **options)[source] , IPV4或者IPV6地址,字符串形式,例如192.0.2.30 或者2a02:42fe::4 在HTML中表现为TextInput标签。参数protocol 默认值为‘both’,可选‘IPv4’或者‘IPv6’,表示你的IP地址类型。 |
NullBooleanField | 类似布尔字段,只不过额外允许NULL 作为选项之一。 |
PositiveIntegerField | 正整数字段,包含0,最大2147483647。 |
PositiveSmallIntegerField | 较小的正整数字段,从0到32767。 |
SlugField | slug是一个新闻行业的术语。一个slug就是一个某种东西的简短标签,包含字母、数字、下划线或者连接线,通常用于URLs中。可以设置max_length参数,默认为50。 |
SmallIntegerField | 小整数,包含-32768到32767。 |
TextField | 大量文本内容,在HTML中表现为Textarea标签,最常用的字段类型之一!如果你为它设置一个max_length参数,那么在前端页面中会受到输入字符数量限制,然而在模型和数据库层面却不受影响。只有CharField才能同时作用于两者。 |
TimeField | 时间字段,Python中datetime.time的实例。接收同DateField一样的参数,只作用于小时、分和秒。 |
URLField | 一个用于保存URL地址的字符串类型,默认最大长度200。 |
UUIDField | 用于保存通用唯一识别码(Universally Unique Identifier)的字段。使用Python的UUID类。在PostgreSQL数据库中保存为uuid类型,其它数据库中为char(32)。这个字段是自增主键的最佳替代品,后面有例子展示。 |
1.FileField:
class FileField(upload_to=None, max_length=100, **options)[source]
上传文件字段(不能设置为主键)。默认情况下,该字段在HTML中表现为一个ClearableFileInput标签。在数据库内,我们实际保存的是一个字符串类型,默认最大长度100,可以通过max_length参数自定义。真实的文件是保存在服务器的文件系统内的。
重要参数
upload_to
用于设置上传地址的目录和文件名。如下例所示:class MyModel(models.Model): # 文件被传至`MEDIA_ROOT/uploads`目录,MEDIA_ROOT由你在settings文件中设置 upload = models.FileField(upload_to='uploads/') # 或者 # 被传到`MEDIA_ROOT/uploads/2015/01/30`目录,增加了一个时间划分 upload = models.FileField(upload_to='uploads/%Y/%m/%d/')
Django很人性化地帮我们实现了根据日期生成目录的方式!
upload_to
参数也可以接收一个回调函数,该函数返回具体的路径字符串,如下例:def user_directory_path(instance, filename): #文件上传到MEDIA_ROOT/user_<id>/<filename>目录中 return 'user_{0}/{1}'.format(instance.user.id, filename) class MyModel(models.Model): upload = models.FileField(upload_to=user_directory_path)
例子中,
user_directory_path
这种回调函数,必须接收两个参数,然后返回一个Unix风格的路径字符串。参数instace
代表一个定义了FileField
的模型的实例,说白了就是当前数据记录。filename
是原本的文件名。
2.ImageField:
class ImageField(upload_to=None, height_field=None, width_field=None, max_length=100, **options)[source]
用于保存图像文件的字段。其基本用法和特性与FileField一样,只不过多了两个属性height和width。默认情况下,该字段在HTML中表现为一个ClearableFileInput标签。在数据库内,我们实际保存的是一个字符串类型,默认最大长度100,可以通过max_length参数自定义。真实的图片是保存在服务器的文件系统内的。
height_field
参数:保存有图片高度信息的模型字段名。width_field
参数:保存有图片宽度信息的模型字段名。使用Django的ImageField需要提前安装pillow模块,pip install pillow即可。
使用FileField或者ImageField字段的步骤:
- 在settings文件中,配置
MEDIA_ROOT
,作为你上传文件在服务器中的基本路径(为了性能考虑,这些文件不会被储存在数据库中)。再配置个MEDIA_URL
,作为公用URL,指向上传文件的基本路径。请确保Web服务器的用户账号对该目录具有写的权限。- 添加FileField或者ImageField字段到你的模型中,定义好
upload_to
参数,文件最终会放在MEDIA_ROOT
目录的“upload_to”子目录中。- 所有真正被保存在数据库中的,只是指向你上传文件路径的字符串而已。可以通过url属性,在Django的模板中方便的访问这些文件。例如,假设你有一个ImageField字段,名叫
mug_shot
,那么在Django模板的HTML文件中,可以使用{{ object.mug_shot.url }}
来获取该文件。其中的object用你具体的对象名称代替。- 可以通过
name
和size
属性,获取文件的名称和大小信息。安全建议:
无论你如何保存上传的文件,一定要注意他们的内容和格式,避免安全漏洞!务必对所有的上传文件进行安全检查,确保它们不出问题!如果你不加任何检查就盲目的让任何人上传文件到你的服务器文档根目录内,比如上传了一个CGI或者PHP脚本,很可能就会被访问的用户执行,这具有致命的危害。
3.FilePathField:
一种用来保存文件路径信息的字段。在数据表内以字符串的形式存在,默认最大长度100,可以通过max_length参数设置。
class FilePathField(path=None, match=None, recursive=False, max_length=100, **options)[source] 参数介绍: 1. path:必须指定的参数。表示一个系统绝对路径。 2. match:可选参数,一个正则表达式,用于过滤文件名。只匹配基本文件名,不匹配路径。例如foo.*\.txt$,只匹配文件名foo23.txt,不匹配bar.txt与foo23.png。 3. recursive:可选参数,只能是True或者False。默认False。决定是否包含子目录,也就是是否递归的意思。 4. allow_files:可选参数,只能是True或者False。默认为True。决定是否应该将文件名包括在内。它和allow_folders其中,必须有一个为True。 5. allow_folders:可选参数,只能是True或者False。默认为False。决定是否应该将目录名包括在内。 比如: FilePathField(path="/home/images", match="foo.*", recursive=True) 它只匹配/home/images/foo.png,但不匹配/home/images/foo/bar.png,因为默认情况,只匹配文件名,而不管路径是怎么样的。
4.UUIDField:
数据库无法自己生成uuid,因此需要如下使用default参数:
import uuid # Python的内置模块 from django.db import models class MyUUIDModel(models.Model): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) # 其它字段