引言:
数据是非常重要的,但是对于数据的操作是非常麻烦的,因此产生了数据库来处理数据。数据库软件可以通过指令操作磁盘中的数据(增删改查)。这和我们的语言又有什么关系呢?你想想,数据库是很强大吧,能够处理很多的事情,如果能够配合语言就会能处理更多的事情。
于是就产生了pymysql模块,pymysql的作用是什么呢?简而言之就是python语言能够通过数据库间接控制底层的数据。这就需要数据库软件能够给python开放一个接口。实际上我们在python端利用pymysql模块写的操作底层数据库本质上依然是在写sql语句。只不过是换了个地方写sql而已。虽然能够实现功能,但不符合python的思想,因此python在上面又有一层,而这一层就是ORM,ORM 这里写的语句都是python语言中的类、对象。通过这样的方式让类、对象与sql产生对应关系。所以本质上ORM就是一个引擎,把类、对象这样的语法翻译成sql语句。所以我们下面需要学习相对于数据库的ORM的增删改查
一:ORM介绍
1:ORM介绍
对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术。这里的mapping指的是python中的类与数据库的映射
简单的说,ORM是通过使用描述对象和数据库之间映射的元数据,将程序中的对象自动持久化到关系数据库中。
ORM在业务逻辑层和数据库层之间充当了桥梁的作用。
- MVC或者MVC框架中包括一个重要的部分,就是ORM,它实现了数据模型与数据库的解耦,即数据模型的设计不需要依赖于特定的数据库,通过简单的配置就可以轻松更换数据库,这极大的减轻了开发人员的工作量,不需要面对因数据库变更而导致的无效劳动
- ORM是“对象-关系-映射”的简称。
类-----------表
类属性-----表字段
类对象-----表记录
1 #sql中的表 2 3 #创建表: 4 CREATE TABLE employee( 5 id INT PRIMARY KEY auto_increment , 6 name VARCHAR (20), 7 gender BIT default 1, 8 birthday DATA , 9 department VARCHAR (20), 10 salary DECIMAL (8,2) unsigned, 11 ); 12 13 14 #sql中的表纪录 15 16 #添加一条表纪录: 17 INSERT employee (name,gender,birthday,salary,department) 18 VALUES ("alex",1,"1985-12-12",8000,"保洁部"); 19 20 #查询一条表纪录: 21 SELECT * FROM employee WHERE age=24; 22 23 #更新一条表纪录: 24 UPDATE employee SET birthday="1989-10-24" WHERE id=1; 25 26 #删除一条表纪录: 27 DELETE FROM employee WHERE name="alex" 28 29 30 31 32 33 #python的类 34 class Employee(models.Model): 35 id=models.AutoField(primary_key=True) 36 name=models.CharField(max_length=32) 37 gender=models.BooleanField() 38 birthday=models.DateField() 39 department=models.CharField(max_length=32) 40 salary=models.DecimalField(max_digits=8,decimal_places=2) 41 42 43 #python的类对象 44 #添加一条表纪录: 45 emp=Employee(name="alex",gender=True,birthday="1985-12-12",epartment="保洁部") 46 emp.save() 47 #查询一条表纪录: 48 Employee.objects.filter(age=24) 49 #更新一条表纪录: 50 Employee.objects.filter(id=1).update(birthday="1989-10-24") 51 #删除一条表纪录: 52 Employee.objects.filter(name="alex").delete()
2:ORM的优势
ORM解决的主要问题是对象和关系的映射。它通常将一个类和一张表一一对应,类的每个实例对应表中的一条记录,类的每个属性对应表中的每个字段。
ORM提供了对数据库的映射,不用直接编写SQL代码,只需操作对象就能对数据库操作数据。即使后台数据库更改了也不会影响,比如MySQL更改为Oracle。一旦更改,sql语法不同,整个就得重新更改。而ORM则不同,只需要更改ORM数据库引擎就可以了。因为ORM就是按照引擎翻译成SQL的。
让软件开发人员专注于业务逻辑的处理,提高了开发效率。
3:ORM的劣势
ORM的缺点是会在一定程度上牺牲程序的执行效率。
ORM的操作是有限的,也就是ORM定义好的操作是可以完成的,一些复杂的查询操作是完成不了。
ORM用多了SQL语句就不会写了,关系数据库相关技能退化...
4:ORM总结
ORM只是一种工具,工具确实能解决一些重复,简单的劳动。这是不可否认的。
但我们不能指望某个工具能一劳永逸地解决所有问题,一些特殊问题还是需要特殊处理的。
但是在整个软件开发过程中需要特殊处理的情况应该都是很少的,否则所谓的工具也就失去了它存在的意义。
二:操作ORM前的准备
1:settings.py文件
请参考博文:Django--配置文件
2:__init__.py文件 (项目文件下的)
(1)指定ORM引擎
django默认你导入的驱动是MySQLdb,可是MySQLdb(主要用在py2中) 对于py3有很大问题,所以我们需要更改驱动为PyMySQL
import pymysql pymysql.install_as_MySQLdb()
三:创建表
1:创建表结构
在models.py文件中
from django.db import models # Create your models here. class Book(models.Model): #类名对应表名,属性对应字段 id=models.AutoField(primary_key=True) #注意当我们在使用主键时,如果不知到主键值,我们可以用pk表示,这是一个万能的表示方式 title=models.CharField(max_length=32) state=models.BooleanField() pub_date=models.DateField() price=models.DecimalField(max_digits=8,decimal_places=2) publish=models.CharField(max_length=32)
执行命令:通过两条数据库迁移命令即可在指定的数据库中创建表
python manage.py makemigrations #同步 python manage.py migrate
(数据库迁移:django会把setting中的 INSTALLED_APPS中每一个应用中的models对应类翻译成sql语句并创建成数据库中的表)
补充:
当我们已经创建完表结构,而且表里面已经有数据了,那么我们想要在一张表格里在添加一列(记录),那么以前的记录里对这个先添加的字段是没有数据的,这个时候我们就可以设置一个默认值了。而且是必须创建,不创建的话是通过不了的。
如下面:
clssses = models.CharField(max_length=32 ,default=100)
2:字段和参数
字段
''' <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 1、models.AutoField 自增列 = int(11) 2 如果没有的话,默认会生成一个名称为 id 的列,如果要显示的自定义一个自增列,必须将给列设置为主键 primary_key=True。 3 2、models.CharField 字符串字段 4 必须 max_length 参数 5 3、models.BooleanField 布尔类型=tinyint(1) 6 不能为空,Blank=True 7 4、models.ComaSeparatedIntegerField 用逗号分割的数字=varchar 8 继承CharField,所以必须 max_lenght 参数 9 5、models.DateField 日期类型 date 10 对于参数,auto_now = True 则每次更新都会更新这个时间;auto_now_add 则只是第一次创建添加,之后的更新不再改变。 11 6、models.DateTimeField 日期类型 datetime 12 同DateField的参数 13 7、models.Decimal 十进制小数类型 = decimal 14 必须指定整数位max_digits和小数位decimal_places 15 8、models.EmailField 字符串类型(正则表达式邮箱) =varchar 16 对字符串进行正则表达式 17 9、models.FloatField 浮点类型 = double 18 10、models.IntegerField 整形 19 11、models.BigIntegerField 长整形 20 integer_field_ranges = { 21 'SmallIntegerField': (-32768, 32767), 22 'IntegerField': (-2147483648, 2147483647), 23 'BigIntegerField': (-9223372036854775808, 9223372036854775807), 24 'PositiveSmallIntegerField': (0, 32767), 25 'PositiveIntegerField': (0, 2147483647), 26 } 27 12、models.IPAddressField 字符串类型(ip4正则表达式) 28 13、models.GenericIPAddressField 字符串类型(ip4和ip6是可选的) 29 参数protocol可以是:both、ipv4、ipv6 30 验证时,会根据设置报错 31 14、models.NullBooleanField 允许为空的布尔类型 32 15、models.PositiveIntegerFiel 正Integer 33 16、models.PositiveSmallIntegerField 正smallInteger 34 17、models.SlugField 减号、下划线、字母、数字 35 18、models.SmallIntegerField 数字 36 数据库中的字段有:tinyint、smallint、int、bigint 37 19、models.TextField 字符串=longtext 38 20、models.TimeField 时间 HH:MM[:ss[.uuuuuu]] 39 21、models.URLField 字符串,地址正则表达式 40 22、models.BinaryField 二进制 41 23、models.ImageField 图片 42 24、models.FilePathField 文件
参数:
(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 中的选项。
1 1、null=True 2 数据库中字段是否可以为空 3 2、blank=True 4 django的 Admin 中添加数据时是否可允许空值 5 3、primary_key = False 6 主键,对AutoField设置主键后,就会代替原来的自增 id 列 7 4、auto_now 和 auto_now_add 8 auto_now 自动创建---无论添加或修改,都是当前操作的时间 9 auto_now_add 自动创建---永远是创建时的时间 10 5、choices 11 GENDER_CHOICE = ( 12 (u'M', u'Male'), 13 (u'F', u'Female'), 14 ) 15 gender = models.CharField(max_length=2,choices = GENDER_CHOICE) 16 6、max_length 17 7、default 默认值 18 8、verbose_name Admin中字段的显示名称 19 9、name|db_column 数据库中的字段名称 20 10、unique=True 不允许重复 21 11、db_index = True 数据库索引 22 12、editable=True 在Admin里是否可编辑 23 13、error_messages=None 错误提示 24 14、auto_created=False 自动创建 25 15、help_text 在Admin中提示帮助信息 26 16、validators=[] 27 17、upload-to 上传到哪个位置,更多与image,filepath配合使用
四:表的操作
1:增
方式一:实例化对象,对应的就是表记录
book=Book(title='python',price=123,pub_date="2012-12-12",publish="人民出版社") book.save() print(book.nid)
方式二:使用object管理器
注意:create方法返回当前生成的表记录对象
book = Book.objects.create(title='linux',price=222,pub_date="2012-12-12",publish="人民出版社") print(book.nid)
方式三:批量
2:查
参考:
3:删
删除方法就是 delete()。它运行时立即删除对象而不返回任何值
案例:
Book.objects.filter(price=100).delete() #这个可删除多个
要注意的是: delete() 方法是 QuerySet 上的方法
Book.objects.get(nid=10).delete() #这个只删除一个,因为get是查询结果有且只有一个才执行
4:改
update()方法对于任何结果集(QuerySet)均有效,这意味着你可以同时更新多条记录update()方法会返回一个整型数值,表示受影响的记录条数。
案例:
Book.objects.filter(nid=edit_book_id).update(price=111) Book.objects.filter(price=111).update(publish="南京出版社")
五:表的操作-案例
参考: