ORM,实现了数据模型与数据库的解耦,即数据模型的设计不需要依赖特定的数据库,通过简单的配置,就可以轻松更换数据库,这极大的减轻了开发人员的工作量,不需要面对因数据库变动而导致的无效劳动
ORM是 对象-关系-映射 的简称:object relational mapping
类对象--->sql---->pymysql---->mysql服务端---->磁盘,ORM就是将类对象的语法翻译成sql语句的一个引擎
原生sql和python的orm代码对比
#sql中创建表 create table empluyee( id int primary key auto_increment, name varchar(20), gender bit default 1, birthday data, department varchar(10), salary decimal(8,2) unsigned, ) # 添加表记录 insert employee (name,gender,birthday,salary,department) values ('alex',1,'1977-12-12',4000,'cleaning'); #查询表记录 select * from employee where name='alex'; #更新表记录 update employee set birthday='1966-01-01' where name='alex'; #删除表记录 delete from employee where name='alex'; #Django中models.py class Employee(models.Model): id = models.AutoField(primary_key=True) name=models.CharField(max_length=32) gender=models.BooleanField() birthday=models.DateField() department=models.CharField(max_length=32) salary=models.DecimalField(max_digits=8,decimal_places=2) #python的类对象 emp=Employee(name='alex',gender=True,birthday='1981-01-01',department='cleaning') emp.save() #查询一条表记录 Employee.objects.filter(age=24) #更新一条表记录 Employee.objects.filter(id=1).update(birthday='1982-02-02') #删除一条表记录 Employee.objects.filter(id=1).delete()
1.在项目settings.py中修改DATABASES DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'HOST':'127.0.0.1', 'PORT':3306, 'NAME':'ormtest', # 要连接的mysql库名 'USER':'root', 'PASSWORD':'123456', } } 2.在项目__init__.py中 import pymysql # MySQLdb()是Django用来连接mysql数据的工具,这里用pymysql代替MySQLdb pymysql.install_as_MySQLdb() 3.在应用文件夹中models.py中写入创建数据的类 class UserInfo(models.Model): #create table userinfo(id int primary key auto_increment, # name varchar(16),age int,current_date date) id = models.AutoField(primary_key=True) name = models.CharField(max_length=16) age = models.IntegerField() current_date = models.DateField() 4.在命令行(Terminal)中输入命令 python manage.py makemigrations # 创建一条记录,数据库操作的记录 python manage.py migrate # 连接数据库,并按model.py中写类来生成表,以及生成django自带的表
在Django中可以用外部的py文件操作models.py,来操作数据库 1.在项目下创建 xx.py文件,写入代码 # 外部文件使用jdango的models,需要配置jdango环境 import os if __name__ == '__main__': os.enveron.setdefault("DJANGO_SETTINGS_MODULE","ormhw.settings") import django # 项目名称 settings.py django.setup() from app01 import models obj_lst = [] for i in range(1,10): obj = models.Books( title = 'python%s'%i, price = 120+i, pub_date = '101%s-10-10'%i, publish = 'beida' if i<5 else 'tsinghua' ) obj_lst.append(obj) models.Books.objects.bulk_create(obj_lst) 2.直接运行xx.py 文件,就可以执行代码,对数据库做操作
Django项目通过浏览器admin后台管理数据库
# 在app 中的admin.py中添加需要管理的类,即创建的表 from django.contrib import admin from app01 import models # Register your models here. admin.site.register(models.Book) #在pycharm terminal中输入命令 python manage.py createsuperuser #接着输入username/password,email可以不用输入,直接回车 #运行项目,在浏览器上输入127.0.0.1:8000/admin #输入用户名密码即可管理添加的数据库表了
''' 1.CharField 字符串字段,必须要有一个参数:max_length 2.IntergerField 保存一个整数 3.DecimalField 一个浮点数,必须提供两个参数:max_digits 总位数,decimal_places 小数位数 4.AutoField 表示一个自增字段 5.BooleanField A true/false field.admin 用 checkbox 来表示此类字段 6.TextField 一个容量很大的文本字段 admin用一个<textarea>表示该字段数据 7.EmailField 一个带有检查Email合法性的 CharField,不接受 max_length参数 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">部件表示该字段保存的数据(一个文件上传部件) 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 15.XMLField 一个校验值是否为合法XML的 TextField,必须提供参数: schema_path, 它是一个用来校验文本的 RelaxNG schema #的文件系统路径. 16.FilePathField 17.IPAaddressField 一个字符串形式的 IP 地址, (i.e. "24.124.1.30"). '''
''' 1.null 如果为True ,Django将用NULL来在数据库存储空值,默认值是false 2.blank 如果为True,该字段允许不添,默认为false 这与null不同,null纯粹是数据库范畴的,blank是数据验证范畴的 如果一个字段blank=True,表单的验证将允许该字段为空值,如果blank=false,该字段就必须有值 3.default 字段的默认值,可以是一个值或者可调用对象。如果可调用,每有新对象被创建它都会被调用,如果你的字段没有设置为可以为空,那么将来如果我们后添加一个字段,这个字段就要给一个default值 4.primary_key 如果为True,那么这个字段就是模型的主键。如果没有指定任何一个字段的primary_key=True,Django就会自动添加一个IntegerField字段作为主键,所以除非你想覆盖默认的主键行为,否则抹油必要设置一个字段的primary_key=True 5.unique 如果设置值为True,这个数据字段的值在整张表中必须是唯一的 6.choices 由二元组组成一个可迭代对象,用来给字段提供选择项。如果设置choices,默认的表单将是一个选择框而不是标准的文本框,而且这个选择框的选项就是choices中的选项 7.db_index 如果db_index=True,则代表将此字段设置为数据库索引 8.DatetimeField DateField TimeField 这三个时间段,都可以设置如下属性 auto_now_add 配置auto_now_add=True,创建数据记录的时候,会把当前时间添加到数据库 auto_now 配置auto_now=True,每次更新数据记录都会跟新该字段,标识这条记录的最后一次的修改时间 '''
'AutoField': 'integer AUTO_INCREMENT', 'BigAutoField': 'bigint AUTO_INCREMENT', 'BinaryField': 'longblob', 'BooleanField': 'bool', 'CharField': 'varchar(%(max_length)s)', 'CommaSeparatedIntegerField': 'varchar(%(max_length)s)', 'DateField': 'date', 'DateTimeField': 'datetime', 'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)', 'DurationField': 'bigint', 'FileField': 'varchar(%(max_length)s)', 'FilePathField': 'varchar(%(max_length)s)', 'FloatField': 'double precision', 'IntegerField': 'integer', 'BigIntegerField': 'bigint', 'IPAddressField': 'char(15)', 'GenericIPAddressField': 'char(39)', 'NullBooleanField': 'bool', 'OneToOneField': 'integer', 'PositiveIntegerField': 'integer UNSIGNED', 'PositiveSmallIntegerField': 'smallint UNSIGNED', 'SlugField': 'varchar(%(max_length)s)', 'SmallIntegerField': 'smallint', 'TextField': 'longtext', 'TimeField': 'time', 'UUIDField': 'char(32)',
python中 orm 的对应关系有三种
类 ----------------->表
类对象------------->行(表记录)
类属性------------->表字段
首先想要操作表的增删改查,需要先导入这个表
# views.py中导入需要操作的表 from app01 import models def index(request): ''' 添加表记录,等数据库操作 ''' obj=models.Book(title='python',price='120',pubdate='2019-10-10',publish='人民出版社') obj.save() # create 方法插入数据,返回的是object对象 obj=models.Book。objects.create(title='python',price='120',pubdate='2019-10-10',publish='人民出版社') print(obj.title) # 批量创建 objs = [] for i in range(20): obj = models.UserInfo( name='alex%s'%i, age = 20 + i, current_date='1990-01-01' ) objs.append(obj) models.UserInfo.objects.bulk_create(objs) # 创建方法:updata_or_create,有就更新,没有就创建 models.UserInfo.objects.update_or_create( name='wusir111', defaults={ 'age':35, 'current_date':'1982-03-03' } )
# 简单查询,获取所有对象,即表记录以对象的形式返回,queryset all_objs = models.UserInfo.objects.all() print(all_objs) #<QuerySet [<UserInfo: UserInfo object>, <UserInfo: UserInfo object>]> for obj in all_objs: print(obj.name) # filter(**kwargs) 条件查询,查询不到内容,不会报错,返回空 queryest objs = models.UserInfo.objects.filter(id=1) print(objs) # <QuerySet [<UserInfo: aliex>]> objs1 = models.UserInfo.objects.filter(name = 'wusir') print(objs1) # <QuerySet [<UserInfo: wusir>]> # get(**kwargs),返回的是model对象,有且只有一个结果。如果没有会报错,有多条记录也会报错 obj = models.UserInfo.objects.get(id = 3) print(obj) # aliex # obj = models.UserInfo.objects.get(name='jackma') # print(obj) # 查询记录有多条或者没有的时候报错 get() returned more than one UserInfo -- it returned 2! # order_by(*field) queryset类型的数据来调用,对查询的结果排序,默认按照id来升序的,返回值还是queryset类型 query = models.UserInfo.objects.all().order_by('age','-id') print(query) # 按照age从小到大排序,age相同的记录按照id 从大到小排序 # reverse() queryset类型的数据调用,对返回结果进行反向排序,返回值还是queryset类型 query = models.UserInfo.objects.all().order_by('id').reverse() print(query) # 返回queryset类型 # count() queryset类型的数据调用,返回数据库中匹配查询到的数量 num = models.UserInfo.objects.all().count() print(num) # first() queryset类型的数据调用,返回第一条记录,得到的是model对象 # first() queryset类型的数据调用,返回最后一条记录,得到的是model对象 fobj = models.UserInfo.objects.all().first() lobj = models.UserInfo.objects.all().last() # exists() queryset类型的数据调用,如果queryset包含数据,则返回True,否则返回False obj = models.UserInfo.objects.filter(id=50).exists() print(obj) # values 返回queryset类型数据,元素是dick类型 query = models.UserInfo.objects.filter(id__gt=25).values() # 查询id>25的结果 print(query) #<QuerySet [{'id': 26, 'name': 'wusir111', 'age': 35, 'current_date': datetime.date(1982, 3, 3)}]> # value_list 返回queryset类型数据,元素列表里面套元祖 query = models.UserInfo.objects.filter(id__gt=25).values_list() # 查询id>25的结果 print(query) # <QuerySet [(26, 'wusir111', 35, datetime.date(1982, 3, 3))]> #distinct 去重,values 和 values_list 得到的queryset类型的数据来调用
Book.objects.filter(price_in=[110,220,210]) # 查询price值等于这三个里面任意一个的对象,返回所有符合条件的对象 Book.objects.filter(price_gt=100) # price大于100的对象。大于等于price_gte Book.objects.filter(price_lt=100) # price小于100的对象。小于等于price_lte Book.objects.filter(price_range=[100,200])#相当于sql 的between and,大于等于100,小于等于200 Book.objects.filter(title_contains='python')# title中包含python的 Book.objects.filter(title_icontains='python')# 不区分大小写 Book.objects.filter(title_startswith='py')# 以什么开头,不区分大小写 Book.objects.filter(pub_date__year=2012) all_books=models.Book.objects.filter(pub_date__year=2012)# 找2012年所有的书 all_books=models.Book.objecs.filter(pub_date__year__gt=2012)#找大于2012年所有的书籍
# delete()方法的调用者可以是一个model对象,也可以是一个queryset集合。它立即执行删除对象,没有返回值 obj.delete() # 也可以一次删除多个对象,每个Queryset都有一个delete方法,它一次性删除queryset中的所有对象 models.Book.objects.filter(pub_date__year=2012).delete()#删除2015年的所有书籍 models.UserInfo.objects.get(id=3).delete() # 删除id=3 的记录 models.UserInfo.objects.filter(name='jackma').delete() # 删除 name='jackma'的所有记录 models.UserInfo.objects.all().delete() # 删除所有
# 更新 update()方法,model对象不能调用更新方法,只能queryset调用 models.UserInfo.objects.filter(name='wusir').update(age=3)
update()方法对于任何结果集(queryset)均有效,这意味着你可以同时更新多条记录,update()方法会返回一个整形数值,表示受影响的记录条数