Django的模型层Model与ORM数据库操作
模型层(Model)
模型是你的数据的唯一的、确定的信息源。 它包含你所储存数据的必要字段和行为。 通常,每个模型对应数据库中唯一的一张表。
参考文档:https://yiyibooks.cn/xx/Django_1.11.6/topics/db/models.html
https://django-chinese-doc.readthedocs.io/zh_CN/1.10.x/topics/db/models.html
https://docs.djangoproject.com/en/1.11/topics/db/models/
一、模型介绍
1.1、基础:
- 每个模型都是一个Python类,它们都是
django.db.models.Model
的子类。 - 每一个模型属性都代表数据库中的一个字段。
- 通过所有这一切,Django为你提供一个自动生成的数据库访问API;
-
数据库表名
模型类如果未指明表名,Django默认以小写app应用名_小写模型类名为数据库表名。
可通过db_table指明数据库表名。
-
关于主键
django会为表创建自动增长的主键列,每个模型只能有一个主键列,如果使用选项设置某属性为主键列后django不会再创建自动增长的主键列。
默认创建的主键列属性为id,可以使用pk代替,pk全拼为primary key。
1.2、简短示例
- 其实模型层就是我们数据库的表,只不过转化为python的写法,要放置在项目的字应用的model.py中
- model.py中的class类就是表,类中的元素就是字段
- 这个例子定义一个
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)
first_name
和last_name
是模型的两个字段。 每个字段都被指定成一个类属性,每个属性映射到一个数据库的列。
-
- 上面的
Person
模型会在数据库中创建这样一张表:-
CREATE TABLE login_person ( # login是子应用,person是子应用中对应的class "id" serial NOT NULL PRIMARY KEY, "first_name" varchar(30) NOT NULL, "last_name" varchar(30) NOT NULL );
-
- 这个表的名称login
_person
,是根据模型中的某些元数据自动生成的(app_name + class_name),也可以自定义表的名称,参考这里 数据库表名; id
字段是自动添加的,但这个行为可以被重写。 请参见自动主键字段。- 这个例子中的
CREATE TABLE
SQL 语句使用PostgreSQL 语法格式,要注意的是Django 会根据settings文件 中指定的数据库类型来使用相应的SQL 语句。
- 这个表的名称login
-
二、数据库使用配置
2.1、子应用配置
- 定义好模型之后,接下来你需要告诉Django使用这些模型,你要做的就是修改配置文件中的
INSTALLED_APPS
设置, 在其中添加models.py
所在应用的名称。 - 例如,如果你的应用的模型位于
myapp.models
(文件结构是由manage.py startapp
命令自动创建的),INSTALLED_APPS
部分看上去应该是:- 将子应用注入到项目中
INSTALLED_APPS = [ #... 'myapp', # 将此app注入到项目中 #... ]
- 将子应用注入到项目中
- 当你在
INSTALLED_APPS
中添加新的应用名时,一定要运行命令manage.py migrate
, 你可以事先使用manage.py makemigrations
给应用生成迁移脚本。 - 333
2.2、更改数据库配置
- Django默认使用sqlite数据库,我们要连接mysql或者其他的数据库要更改其配置
- 更改为mysql数据库配置
- 111
-
第一步: ########在setting原来默认的sqlite DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), } } ############修改成mysql如下 DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'test', #你的数据库名称 'USER': 'root', #你的数据库用户名 'PASSWORD': '19941028', #你的数据库密码 'HOST': '', #你的数据库主机,留空默认为localhost 'PORT': '3306', #你的数据库端口 }} 第二步: #由于mysql默认引擎为MySQLdb,在项目的__init__.py文件中添加下面代码 #在python3中须替换为pymysql,可在主配置文件(和项目同名的文件下,不是app配置文件)中增加如下代码 import pymysql pymysql.install_as_MySQLdb() #如果找不到pymysql板块,则通过pip install pymysql进行安装。
-
-
由于mysql默认引擎为MySQLdb,在项目的__init__.py文件中导入mysql模块
三、Django表结构分析
3.1、django表结构
- 首先我们再框架搭建的时候就执行了 python manage.py makemigration && python migrate
- 就可以在数据库中看到我们的框架的表结构了
-
- 由上图可以看出我们的表都是以XX_XX 来区分,login是这个项目的主模块,long下划线后面是你的models.py中建立的表对应的类
四、定义模型类
- 模型类被定义在"应用/models.py"文件中。
- 模型类必须继承自Model类,位于包django.db.models中。
五、字段
-
对于一个模型来说,最重要的是列出该模型在数据库中定义的字段。字段由models类属性指定。 要注意选择的字段名称不要和 models API 冲突,比如
clean
、save
或者delete
等。 - 例子
-
from django.db import models class BooInfo(models.Model): """ 主键,当前会自动生成 """ #名称 name = models.CharField(max_length=10) # 字段最长为10个字符 last_name = models.CharField(max_length=50) # 字段的最长为50个字符 def __str__(self): return self.name 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()
-
- 1111
5.1、字段类型
模型中的每个字段都是 Field
子类的某个实例,Django根据字段类的类型确定以下信息:
- 数据库中字段的类型(e.g.
INTEGER
,VARCHAR
,TEXT
); - 渲染表单时使用的默认HTML widget (e.g.
<input type="text">
,<select>
); - 在Django的admin和自动生成的表单中使用的最低验证要求;
- 字段类型
-
类型 说明 AutoField 自动增长的IntegerField,通常不用指定,不指定时Django会自动创建属性名为id的自动增长属性 BooleanField 布尔字段,值为True或False NullBooleanField 支持Null、True、False三种值 CharField 字符串,参数max_length表示最大字符个数 TextField 大文本字段,一般超过4000个字符时使用 IntegerField 整数 DecimalField 十进制浮点数, 参数max_digits表示总位数, 参数decimal_places表示小数位数 FloatField 浮点数 DateField 日期, 参数auto_now表示每次保存对象时,自动设置该字段为当前时间,用于"最后一次修改"的时间戳,它总是使用当前日期,默认为False; 参数auto_now_add表示当对象第一次被创建时自动设置当前时间,用于创建的时间戳,它总是使用当前日期,默认为False; 参数auto_now_add和auto_now是相互排斥的,组合将会发生错误 TimeField 时间,参数同DateField DateTimeField 日期时间,参数同DateField FileField 上传文件字段 ImageField 继承于FileField,对上传的内容进行校验,确保是有效的图片
5.2 、选项
- 选项
-
选项 说明 null 如果为True,表示允许为空,默认值是False blank 如果为True,则该字段允许为空白,默认值是False db_column 字段的名称,如果未指定,则使用属性的名称 db_index 若值为True, 则在表中会为此字段创建索引,默认值是False default 默认 primary_key 若为True,则该字段会成为模型的主键字段,默认值是False,一般作为AutoField的选项使用 unique 如果为True, 这个字段在表中必须有唯一值,默认值是False
-
- null是数据库范畴的概念,blank是表单验证范畴的
5.3、外键
在设置外键时,需要通过on_delete选项指明主表删除数据时,对于外键引用表数据如何处理,在django.db.models中包含了可选常量:
-
CASCADE级联,删除主表数据时连通一起删除外键表中数据
-
PROTECT保护,通过抛出ProtectedError异常,来阻止删除主表中被外键应用的数据
-
SET_NULL设置为NULL,仅在该字段null=True允许为null时可用
-
SET_DEFAULT设置为默认值,仅在该字段设置了默认值时可用
-
SET()设置为特定值或者调用特定方法
-
DO_NOTHING不做任何操作,如果数据库前置指明级联性,此选项会抛出IntegrityError异常
Django有几十种内置字段类型;你可以在 模型字段参考 找到所有的字段, 如果Django内置字段类型无法满足要求,你也可以自定义字段,参见 自定义模型字段。
六、迁移
将模型类同步到数据库中。
-
1)生成迁移文件
-
python manage.py makemigrations
-
-
2)同步到数据库中
-
python manage.py migrate
-
- 1
七、示例
7.1 创建模型 models.py
- 在models.py 文件中定义模型类。
- 1
-
from django.db import models # Create your models here. # 准备书籍列表信息的模型类 class BookInfo(models.Model): # 创建字段,字段类型... name = models.CharField(max_length=20, verbose_name='名称') pub_date = models.DateField(verbose_name='发布日期',null=True) readcount = models.IntegerField(default=0, verbose_name='阅读量') commentcount = models.IntegerField(default=0, verbose_name='评论量') is_delete = models.BooleanField(default=False, verbose_name='逻辑删除') class Meta: db_table = 'bookinfo' # 指明数据库表名 verbose_name = '图书' # 在admin站点中显示的名称 def __str__(self): """定义每个数据对象的显示信息""" return self.name # 准备人物列表信息的模型类 class PeopleInfo(models.Model): GENDER_CHOICES = ( (0, 'male'), (1, 'female') ) name = models.CharField(max_length=20, verbose_name='名称') gender = models.SmallIntegerField(choices=GENDER_CHOICES, default=0, verbose_name='性别') description = models.CharField(max_length=200, null=True, verbose_name='描述信息') book = models.ForeignKey(BookInfo, on_delete=models.CASCADE, verbose_name='图书') # 外键 is_delete = models.BooleanField(default=False, verbose_name='逻辑删除') class Meta: db_table = 'peopleinfo' verbose_name = '人物信息' def __str__(self): return self.name
-
7.1 添加测试数据
- 在models.py 文件中定义模型类。
-
insert into bookinfo(name, pub_date, readcount,commentcount, is_delete) values ('射雕英雄传', '1980-5-1', 12, 34, 0), ('天龙八部', '1986-7-24', 36, 40, 0), ('笑傲江湖', '1995-12-24', 20, 80, 0), ('雪山飞狐', '1987-11-11', 58, 24, 0);
-
- 111
-
insert into peopleinfo(name, gender, book_id, description, is_delete) values ('郭靖', 1, 1, '降龙十八掌', 0), ('黄蓉', 0, 1, '打狗棍法', 0), ('黄药师', 1, 1, '弹指神通', 0), ('欧阳锋', 1, 1, '蛤蟆功', 0), ('梅超风', 0, 1, '九阴白骨爪', 0), ('乔峰', 1, 2, '降龙十八掌', 0), ('段誉', 1, 2, '六脉神剑', 0), ('虚竹', 1, 2, '天山六阳掌', 0), ('王语嫣', 0, 2, '神仙姐姐', 0), ('令狐冲', 1, 3, '独孤九剑', 0), ('任盈盈', 0, 3, '弹琴', 0), ('岳不群', 1, 3, '华山剑法', 0), ('东方不败', 0, 3, '葵花宝典', 0), ('胡斐', 1, 4, '胡家刀法', 0), ('苗若兰', 0, 4, '黄衣', 0), ('程灵素', 0, 4, '医术', 0), ('袁紫衣', 0, 4, '六合拳', 0);
-
八、shell工具
-
Django的manage工具提供了shell命令,帮助我们配置好当前工程的运行环境(如连接好数据库等),以便可以直接在终端中执行测试python语句。
通过如下命令进入shell
-
python manage.py shell
-
-
- 导入两个模型类,以便后续使用
-
from book.models import BookInfo,PeopleInfo
-
-
- 执行我们的orm语句 即可 这是单纯的属于python的shell操作
-
- 333
九、数据库更改表名
- 我们、在models中建立了表后,如果表名建立错误怎么办呢?我们在model中更改表名
- 在models中的表类中加入以下配置
-
class Meta: db_table = 'bookinfo' # 指明数据库表名 verbose_name = '图书' # 在admin站点中显示的名称
-
- 范例
-
# 准备书籍列表信息的模型类 class BookInfo(models.Model): # 创建字段,字段类型... name = models.CharField(max_length=20, verbose_name='名称') pub_date = models.DateField(verbose_name='发布日期',null=True) readcount = models.IntegerField(default=0, verbose_name='阅读量') commentcount = models.IntegerField(default=0, verbose_name='评论量') is_delete = models.BooleanField(default=False, verbose_name='逻辑删除') class Meta: db_table = 'bookinfo' # 指明数据库表名 verbose_name = '图书' # 在admin站点中显示的名称 def __str__(self): """定义每个数据对象的显示信息""" return self.name
-
一、ORM介绍
orm其实就是对象关系映射,内部ORM 将其转化成对应SQL语句再去执行
映射关系:
表名 --------------------》类名
字段--------------------》属性
表记录-----------------》类实例化对象
开发者通过操作类和对象,内部
ORM的两大功能:
操作表:
- 创建表
- 修改表
- 删除表
操作数据行:
- 增删改查
其实用django实现的models文件就是底层调用了pymysql这个模块
ORM利用pymysql第三方工具链接数据库
Django没办法帮我们创建数据库,只能我们创建完之后告诉它,让django去链接
创建表之前的准备工作
一、自己创建数据库
二、在settings里面配置mysql数据库链接
sqlite3------改为mysql
你的django再创建的时候执行完settings后还会执行你创建的app中的init文件 你再在你的app文件中的init中导入pymsql
在setting中更改导入的信息先注释DATABSE再导入下面的信息
# DATABASES = { # 'default': { # 'ENGINE': 'django.db.backends.sqlite3', # 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), # } # } DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME':'db5', # 要连接的数据库,连接前需要创建好 'USER':'root', # 连接数据库的用户名 'PASSWORD':'zhaoyun', # 连接数据库的密码 'HOST':'127.0.0.1', # 连接主机,默认本级 'PORT':3306 # 端口 默认3306 } }
因为我们用的是python3版本的解释器 ,默认是支持python2的解释器
然后再去你的app下的init文件中导入信息:
import pymysql pymysql.install_as_MySQLdb()
再去创建的app中的models中设置你的sql信息
from django.db import models # Create your models here. class Book(models.Model): nid = models.AutoField(primary_key = True) #括号内是设置主键 这是设置一个int类型的 title = models.CharField(max_length = 32,unique=True) # 设置一个var类型的 这里面是最大字符的 并且设置唯一 pricle = models.DecimalField(max_digits = 8,decimal_places=2)# 999999.99 publish = models.CharField(max_length=32) # 设置最大字符
执行命令创建:(需要记住的!!!)
python3 manage.py makemigrations 创建脚本 python3 manage.py migrate 迁移
这两个语句在你的pycharm的下面
这里执行
也可以点击pycharm的Tools然后选择 Run manage.py make 然后直接输入makemigrations 和migrate 即可
在下部依次输入执行:
makemigrations
migrate
更多字段:
''' <1> CharField 字符串字段, 用于较短的字符串. CharField 要求必须有一个参数 maxlength, 用于从数据库层和Django校验层限制该字段所允许的最大字符数. <2> IntegerField #用于保存一个整数. <3> FloatField 一个浮点数. 必须 提供两个参数: 参数 描述 max_digits 总位数(不包括小数点和符号) decimal_places 小数位数 举例来说, 要保存最大值为 999 (小数点后保存2位),你要这样定义字段: models.FloatField(..., max_digits=5, decimal_places=2) 要保存最大值一百万(小数点后保存10位)的话,你要这样定义: models.FloatField(..., max_digits=19, decimal_places=10) admin 用一个文本框(<input type="text">)表示该字段保存的数据. <4> AutoField 一个 IntegerField, 添加记录时它会自动增长. 你通常不需要直接使用这个字段; 自定义一个主键:my_id=models.AutoField(primary_key=True) 如果你不指定主键的话,系统会自动添加一个主键字段到你的 model. <5> BooleanField A true/false field. admin 用 checkbox 来表示此类字段. <6> TextField 一个容量很大的文本字段. admin 用一个 <textarea> (文本区域)表示该字段数据.(一个多行编辑框). <7> EmailField 一个带有检查Email合法性的 CharField,不接受 maxlength 参数. <8> DateField 一个日期字段. 共有下列额外的可选参数: Argument 描述 auto_now 当对象被保存时,自动将该字段的值设置为当前时间.通常用于表示 "last-modified" 时间戳. auto_now_add 当对象首次被创建时,自动将该字段的值设置为当前时间.通常用于表示对象创建时间. (仅仅在admin中有意义...) <9> DateTimeField 一个日期时间字段. 类似 DateField 支持同样的附加选项. <10> ImageField 类似 FileField, 不过要校验上传对象是否是一个合法图片.#它有两个可选参数:height_field和width_field, 如果提供这两个参数,则图片将按提供的高度和宽度规格保存. <11> FileField 一个文件上传字段. 要求一个必须有的参数: upload_to, 一个用于保存上载文件的本地文件系统路径. 这个路径必须包含 strftime #formatting, 该格式将被上载文件的 date/time 替换(so that uploaded files don't fill up the given directory). admin 用一个<input type="file">部件表示该字段保存的数据(一个文件上传部件) . 注意:在一个 model 中使用 FileField 或 ImageField 需要以下步骤: (1)在你的 settings 文件中, 定义一个完整路径给 MEDIA_ROOT 以便让 Django在此处保存上传文件. (出于性能考虑,这些文件并不保存到数据库.) 定义MEDIA_URL 作为该目录的公共 URL. 要确保该目录对 WEB服务器用户帐号是可写的. (2) 在你的 model 中添加 FileField 或 ImageField, 并确保定义了 upload_to 选项,以告诉 Django 使用 MEDIA_ROOT 的哪个子目录保存上传文件.你的数据库中要保存的只是文件的路径(相对于 MEDIA_ROOT). 出于习惯你一定很想使用 Django 提供的 get_<#fieldname>_url 函数.举例来说,如果你的 ImageField 叫作 mug_shot, 你就可以在模板中以 {{ object.#get_mug_shot_url }} 这样的方式得到图像的绝对路径. <12> URLField 用于保存 URL. 若 verify_exists 参数为 True (默认), 给定的 URL 会预先检查是否存在( 即URL是否被有效装入且 没有返回404响应). admin 用一个 <input type="text"> 文本框表示该字段保存的数据(一个单行编辑框) <13> NullBooleanField 类似 BooleanField, 不过允许 NULL 作为其中一个选项. 推荐使用这个字段而不要用 BooleanField 加 null=True 选项 admin 用一个选择框 <select> (三个可选择的值: "Unknown", "Yes" 和 "No" ) 来表示这种字段数据. <14> SlugField "Slug" 是一个报纸术语. slug 是某个东西的小小标记(短签), 只包含字母,数字,下划线和连字符.#它们通常用于URLs 若你使用 Django 开发版本,你可以指定 maxlength. 若 maxlength 未指定, Django 会使用默认长度: 50. #在 以前的 Django 版本,没有任何办法改变50 这个长度. 这暗示了 db_index=True. 它接受一个额外的参数: prepopulate_from, which is a list of fields from which to auto-#populate the slug, via JavaScript,in the object's admin form: models.SlugField (prepopulate_from=("pre_name", "name"))prepopulate_from 不接受 DateTimeFields. <13> XMLField 一个校验值是否为合法XML的 TextField,必须提供参数: schema_path, 它是一个用来校验文本的 RelaxNG schema #的文件系统路径. <14> FilePathField 可选项目为某个特定目录下的文件名. 支持三个特殊的参数, 其中第一个是必须提供的. 参数 描述 path 必需参数. 一个目录的绝对文件系统路径. FilePathField 据此得到可选项目. Example: "/home/images". match 可选参数. 一个正则表达式, 作为一个字符串, FilePathField 将使用它过滤文件名. 注意这个正则表达式只会应用到 base filename 而不是 路径全名. Example: "foo.*\.txt^", 将匹配文件 foo23.txt 却不匹配 bar.txt 或 foo23.gif. recursive可选参数.要么 True 要么 False. 默认值是 False. 是否包括 path 下面的全部子目录. 这三个参数可以同时使用. match 仅应用于 base filename, 而不是路径全名. 那么,这个例子: FilePathField(path="/home/images", match="foo.*", recursive=True) ...会匹配 /home/images/foo.gif 而不匹配 /home/images/foo/bar.gif <15> IPAddressField 一个字符串形式的 IP 地址, (i.e. "24.124.1.30"). <16> CommaSeparatedIntegerField 用于存放逗号分隔的整数值. 类似 CharField, 必须要有maxlength参数. '''
更多参数:
(1)null 如果为True,Django 将用NULL 来在数据库中存储空值。 默认值是 False. (1)blank 如果为True,该字段允许不填。默认为False。 要注意,这与 null 不同。null纯粹是数据库范畴的,而 blank 是数据验证范畴的。 如果一个字段的blank=True,表单的验证将允许该字段是空值。如果字段的blank=False,该字段就是必填的。 (2)default 字段的默认值。可以是一个值或者可调用对象。如果可调用 ,每有新对象被创建它都会被调用。 (3)primary_key 如果为True,那么这个字段就是模型的主键。如果你没有指定任何一个字段的primary_key=True, Django 就会自动添加一个IntegerField字段做为主键,所以除非你想覆盖默认的主键行为, 否则没必要设置任何一个字段的primary_key=True。 (4)unique 如果该值设置为 True, 这个数据字段的值在整张表中必须是唯一的 (5)choices 由二元组组成的一个可迭代对象(例如,列表或元组),用来给字段提供选择项。 如果设置了choices ,默认的表单将是一个选择框而不是标准的文本框,<br>而且这个选择框的选项就是choices 中的选项。
orm中的你的对象的操作就是对应你的sql的语句想要显示你的 sql的语句的演示你需要再你的settings里面加上一段话
: 如果想打印orm转换过程中的sql,需要在settings中进行如下配置:
LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'console':{ 'level':'DEBUG', 'class':'logging.StreamHandler', }, }, 'loggers': { 'django.db.backends': { 'handlers': ['console'], 'propagate': True, 'level':'DEBUG', }, } }
文章参考:https://yiyibooks.cn/xx/Django_1.11.6/topics/db/models.html