一、Django ORM介绍
ORM是什么?:(在django中,根据代码中的类自动生成数据库的表也叫–code first)
Django中内嵌了ORM框架,不需要直接编写SQL语句进行数据库操作,而是通过定义模型类,操作模型类来完成对数据库中表的增删改查和创建等操作。
ORM:Object Relational Mapping(关系对象映射)
- 对数据库的表进行操作(新建,删除,更新等)
- 对表中的数据(每一条数据)进行操作(增删改查)
ORM的优点
数据模型类都在一个地方定义,更容易更新和维护,也利于重用代码。
ORM 有现成的工具,很多功能都可以自动完成,比如数据消除、预处理、事务等等。
它迫使你使用 MVC 架构,ORM 就是天然的 Model,最终使代码更清晰。
基于 ORM 的业务代码比较简单,代码量少,语义性好,容易理解。
新手对于复杂业务容易写出性能不佳的 SQL,有了ORM不必编写复杂的SQL语句, 只需要通过操作模型对象即可同步修改数据表中的数据.
开发中应用ORM将来如果要切换数据库.只需要切换ORM底层对接数据库的驱动【修改配置文件的连接地址即可】
ORM缺点
ORM 库不是轻量级工具,需要花很多精力学习和设置,甚至不同的框架,会存在不同操作的ORM。
对于复杂的业务查询,ORM表达起来比原生的SQL要更加困难和复杂。
ORM操作数据库的性能要比使用原生的SQL差。
ORM 抽象掉了数据库层,开发者无法了解底层的数据库操作,也无法定制一些特殊的 SQL。【自己使用pymysql另外操作即可,用了ORM并不表示当前项目不能使用别的数据库操作工具了。】
二、安装使用
安装mysqlclient
pip install mysqlclient
设置需要连接的数据库
编辑全局配置文件settings.py文件
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql', ###不通数据库类使用不同的后端引擎
'NAME': 'django', ###需要连接的数据库,需要提前创建
'USER': 'root', ###连接时使用的用户名
'PASSWORD': 'root', ###连接时使用的密码
'HOST': 'localhost', ###数据库ip
'PORT': '3306', ###数据库端口
}
}
##########################
如果默认所有的app都使用default的数据库,
如果要每个app都使用一个数据库,可将“default”的名字改成各自的app名字即可。
创建表
编辑app01中的models.py文件
class UserInfo(models.Model): ##创建一个类
name = models.CharField(max_length=32) ###添加的字段名称以及字段类型为字符
password = models.CharField(max_length=64)
age = models.IntegerField() ###字段类型为整数
模型类如果未指明表名db_table,Django默认以 小写app应用名_小写模型类名 为数据库表名。
# class Meta:
# db_table = 'db_study' ####修改表的名称为db_study
字段类型如下:
类型 | 说明 |
---|---|
AutoField | 自动增长的IntegerField,通常不用指定,不指定时Django会自动创建属性名为id的自动增长属性 |
BooleanField | 布尔字段,值为True或False |
NullBooleanField | 支持Null、True、False三种值 |
CharField | 字符串,参数max_length表示最大字符个数,对应mysql中的varchar |
TextField | 大文本字段,一般大段文本(超过4000个字符)才使用。 |
IntegerField | 整数 |
DecimalField | 十进制浮点数, 参数max_digits表示总位数, 参数decimal_places表示小数位数,常用于表示分数和价格 Decimal(max_digits=7, decimal_places=2) ==> 99999.99~ 0.00 |
FloatField | 浮点数 |
DateField | 日期参数auto_now表示每次保存对象时,自动设置该字段为当前时间。参数auto_now_add表示当对象第一次被创建时自动设置当前。参数auto_now_add和auto_now是相互排斥的,一起使用会发生错误。 |
TimeField | 时间,参数同DateField |
DateTimeField | 日期时间,参数同DateField |
FileField | 上传文件字段,django在文件字段中内置了文件上传保存类, django可以通过模型的字段存储自动保存上传文件, 但是, 在数据库中本质上保存的仅仅是文件在项目中的存储路径!! |
ImageField | 继承于FileField,对上传的内容进行校验,确保是有效的图片 |
执行命令创建表
python manage.py makemigrations ###生成迁移文件
python manage.py migrate ###同步数据库
查看数据库表结构
MariaDB [django]> show tables;
+----------------------------+
| Tables_in_django |
+----------------------------+
| app01_userinfo | ###为创建的表名称
| auth_group |
| auth_group_permissions |
| auth_permission |
| auth_user |
| auth_user_groups |
| auth_user_user_permissions |
| django_admin_log |
| django_content_type |
| django_migrations |
| django_session |
+----------------------------+
11 rows in set (0.01 sec)
##########################
MariaDB [django]> desc app01_userinfo;
+----------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+----------------+
| id | bigint(20) | NO | PRI | NULL | auto_increment |
| name | varchar(32) | NO | | NULL | |
| password | varchar(64) | NO | | NULL | |
| age | int(11) | NO | | NULL | |
+----------+-------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)
#########orm会自动添加id字段,并且设置为主键,auto
###djaogo orm创建表时,读取的是注册的app的。按照app的注册顺序创建表
三、操作表
新增表
新建一个类即可
class UserInfo(models.Model):
name = models.CharField(max_length=32)
password = models.CharField(max_length=64)
age = models.IntegerField()
class deployment(models.Model): ###添加deployment表
name = models.CharField(max_length=32)
再次执行
python manage.py makemigrations
python manage.py migrate
查看数据库
MariaDB [django]> show tables;
+----------------------------+
| Tables_in_django |
+----------------------------+
| app01_deployment | ###增加了app01_deployment表
| app01_userinfo |
| auth_group |
| auth_group_permissions |
| auth_permission |
| auth_user |
| auth_user_groups |
| auth_user_user_permissions |
| django_admin_log |
| django_content_type |
| django_migrations |
| django_session |
+----------------------------+
12 rows in set (0.00 sec)
MariaDB [django]>
删除表
删除deployment类,注释掉即可
执行以下命令查看
python manage.py makemigrations
python manage.py migrate
查看数据库,表app01_deployment已经被删除了
MariaDB [django]> show tables;
+----------------------------+
| Tables_in_django |
+----------------------------+
| app01_userinfo |
| auth_group |
| auth_group_permissions |
| auth_permission |
| auth_user |
| auth_user_groups |
| auth_user_user_permissions |
| django_admin_log |
| django_content_type |
| django_migrations |
| django_session |
+----------------------------+
11 rows in set (0.01 sec)
修改表
class study(models.Model):
name = models.CharField(max_length=32)
six = models.CharField(max_length=32)
age = models.CharField(max_length=32)
height = models.IntegerField
class Meta:
db_table = 'db_study' ####修改表的名称为db_study
在全局setings.py文件中添加如下内容,可以看到orm转换sql的过程
import logging
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console':{
'level':'DEBUG',
'class':'logging.StreamHandler',
},
},
'loggers': {
'django.db.backends': {
'handlers': ['console'],
'propagate': True,
'level':'DEBUG',
},
}
}
四、新增/删除字段
添加字段
添加size字段,需要设置默认值,或者指定字段可为空
class UserInfo(models.Model):
name = models.CharField(max_length=32)
password = models.CharField(max_length=64)
age = models.IntegerField()
size = models.IntegerField(default=2) ###设置默认值为2,或者(null=True,blank=True)
如下所示:
MariaDB [django]> desc app01_userinfo;
+----------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+----------------+
| id | bigint(20) | NO | PRI | NULL | auto_increment |
| name | varchar(32) | NO | | NULL | |
| password | varchar(64) | NO | | NULL | |
| age | int(11) | NO | | NULL | |
| size | int(11) | NO | | NULL | | ##新增了size字段
+----------+-------------+------+-----+---------+----------------+
5 rows in set (0.00 sec)
如果不设置默认值或者允许为空,否则会出现以下问题
删除字段
删除size字段
MariaDB [django]> desc app01_userinfo;
+----------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+----------------+
| id | bigint(20) | NO | PRI | NULL | auto_increment |
| name | varchar(32) | NO | | NULL | |
| password | varchar(64) | NO | | NULL | |
| age | int(11) | NO | | NULL | |
| size | int(11) | NO | | NULL | |
+----------+-------------+------+-----+---------+----------------+
5 rows in set (0.00 sec)
注释models.py文件中的size皆可
查看表,size字段已经被删除。
MariaDB [django]> desc app01_userinfo;
+----------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+----------------+
| id | bigint(20) | NO | PRI | NULL | auto_increment |
| name | varchar(32) | NO | | NULL | |
| password | varchar(64) | NO | | NULL | |
| age | int(11) | NO | | NULL | |
+----------+-------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)
五、数据的增删改查
全局urls.py中增加orm的path,如下:
from django.contrib import admin
from django.urls import path
from app01 import views
urlpatterns = [
path('admin/', admin.site.urls),
path('orm/',views.orm) ####添加路由规则
]
编辑app01中views.py文件,添加orm函数,如下:
from django.shortcuts import render,HttpResponse,redirect
from app01.models import UserInfo
def orm(request):
####创建名称为的用户
UserInfo.objects.create(name="lisa",password="123",age="11")
return HttpResponse("成功")
界面访问并查看数据库,如下:
查看数据
MariaDB [django]> select * from app01_userinfo;
+----+------+----------+-----+
| id | name | password | age |
+----+------+----------+-----+
| 19 | lisa | 123 | 11 |
+----+------+----------+-----+
1 row in set (0.01 sec)
MariaDB [django]>
查看orm转换sql的过程
删除
编辑app01中views.py文件,添加orm函数,如下:
def orm(request):
####删除用户
UserInfo.objects.filter(name="lisa").delete() ###删除指定条件查询得到的结果
####删除所有
# UserInfo.objects.all().delete() ###删除表中所有数据
return HttpResponse("成功")
更新
编辑app01中views.py文件,添加orm函数,如下:
def orm(request):
###更新用户数据
UserInfo.objects.filter(name="lisa").update(name="tom",age=22)
return HttpResponse("成功")
查看orm转换sql的过程
查看数据库,结果已经改变
MariaDB [django]> select * from app01_userinfo;
+----+------+----------+-----+
| id | name | password | age |
+----+------+----------+-----+
| 19 | tom | 123 | 22 |
+----+------+----------+-----+
1 row in set (0.01 sec)
查找
查看所有数据
def orm(request):
###查找用户,返回的QuerySet数据
data_list = UserInfo.objects.all()
print(data_list)
return HttpResponse("成功")
查看返回结果
数据库中有4条记录,返回的QuerySet中4个对象数据
查询具体的返回值
def orm(request):
###查找用户
data_list = UserInfo.objects.all()
for item in data_list:
print(item.name,item.id,item.password,item.age)
return HttpResponse("成功")
查看返回结果
根据条件查找
def orm(request):
###查找用户,返回的QuerySet数据
data_list = UserInfo.objects.filter(name="tom")
#data_list = UserInfo.objects.valuesr("name") ###查询某个字段
print(data_list)
return HttpResponse("成功")
查看返回结果
get方法查找
def orm(request):
####get方式获取的是模型数据,可以直接使用句点符获取数据
####此方式只适合查找只有一条记录的数据
data_list = UserInfo.objects.get(name="tom")
#data_list = UserInfo.objects.get(name="tom").id
print(data_list.id,data_list.name,data_list.password)
return HttpResponse("成功")
first、last查找
def orm(request):
###查看第一条记录
data_list = UserInfo.objects.all().first()
print(data_list.age,data_list.id,data_list.name)
return HttpResponse("成功")
MariaDB [django]> select * from app01_userinfo;
+----+-------+----------+-----+
| id | name | password | age |
+----+-------+----------+-----+
| 19 | tom | 123 | 22 |
| 20 | lisa | 123 | 11 |
| 21 | david | 123 | 33 |
| 22 | kaka | 123 | 33 |
+----+-------+----------+-----+
4 rows in set (0.00 sec)
MariaDB [django]>
查看最后一条记录
MariaDB [django]> select * from app01_userinfo;
+----+-------+----------+-----+
| id | name | password | age |
+----+-------+----------+-----+
| 19 | tom | 123 | 22 |
| 20 | lisa | 123 | 11 |
| 21 | david | 123 | 33 |
| 22 | kaka | 123 | 33 |
+----+-------+----------+-----+
4 rows in set (0.00 sec)
反向查询exclude
筛选条件不匹配的对象,返回queryset对象。
def stuinfo(request):
##查询不满足结果的数据
students = stu.objects.exclude(name="张三")
print(students)
return HttpResponse("查询成功")
排序order_by
对查询的结果进行排序
def stuinfo(request):
###对结果进行排序
students = stu.objects.all().order_by("-age") ##按照大小排序
print(students)
return HttpResponse("查询成功")
查询某个数据的数量
def stuinfo(request):
##查询某个属性的个数
students = stu.objects.filter(sex=1).count()
print(students) ###返回的是一个数字
return HttpResponse("查询成功")
values()
value()把结果集中的模型对象转换成字典,并可以设置转换的字段列表,达到减少内存损耗,提高性能
def stuinfo(request):
###只查询某几个字段(结果返回的是字典)
values = stu.objects.all().values("name", "age")
print(values)
返回结果如下:
values_list()
values_list(): 把结果集中的模型对象转换成列表,并可以设置转换的字段列表(元祖),达到减少内存损耗,提高性能
def stuinfo(request):
###只查询某几个字段(结果返回的是字典)
values = stu.objects.all().values_list("name", "age")
print(values)