目录
一 简介
1)作用:
2)Django ORM的模式特征
3)主要使用步骤
二 用法
1 数据库连接
2 创建数据模型
3 Django ORM 字段
①常用字段类型
②常用字段属性
4 基本数据操作--增删改查
5 数据操作常用函数
三 样例1:数据库表操作
1)准备工作
二)建立路由与视图函数对应关系
3)编写视图函数
4)employee数据模型的操作
四 Django ORM跨表操作
1)与外键有关的跨表操作
2)与多对多键有关的跨表操作
3)与一对一键有关的跨表操作
五 Django ORM 聚合与分组查询
1)聚合查询
2)分组查询
编辑
六 Django ORM 中的F和Q函数
1)F函数
2)Q函数
ORM意思是对象关系映射,Django ORM描述Django数据模型类和数据库之间的映射关系,通俗来说就是让一个类和一个数据表进行对应,这使得ORM在数据库层和业务逻辑层之间起到了桥梁的作用。
Django ORM与数据库映射的关系表现为Django中的一个数据模型映射一个数据库表,其基本情况是:类(ajango.db.models.Model)映射到数据库表,类的属性映射为数据库表的字段,类的实例对象则映射为数据行。
①在项目使用的数据库管理系统中建立数据库
②在项目配置文件settings.py中色湖之数据库的连接字符
③在应用程序的models.py文件中编写继承于models.Model的数据模型
④运行python manage.py makemigrations, python manage.py migrate 两个命令生成数据库表
⑤使用Django ORM操作数据库表
首先登录数据库
假设在数据库中创建了test_orm数据库
连接数据库时,我没需要在配置文件settings.py中修改DATABASES代码块
注意:注册应用程序
models.py中有了代码,它所属的应用程序必须在settings.py的INSTALLED_APPS中注册,直接将应用程序名添加到INSTALLED_APPS列表中即可。例如我所创建的应用程序名为myapp:
在此创建一个group模型 有两个属性及user和email。在应用程序目录下的models.py文件下输入以下代码,假设在项目中有一个应用程序名称为myapp
from django.db import models
# Create your models here.
#数据模型一定要继承于models.Model
class Group(models.Model):
#group_name为团体名称,CharField为类型,max_length设置最大字符数
#verbose_name设置在Django Admin管理后台页面上显示的字段名
group_name=models.CharField(max_length=32,verbose_name='团体名称')
#团体备注说明
group_script=models.CharField(max_length=60,verbose_name='备注')
group_name和group_script可以乘坐模型字段,每个字段在类中表现为一个类属性,根据映射关系,每个类属性映射为一个数据表字段
在命令行终端输入以下命令,在mysql中生成数据表
在输入第一个命令时,可能会报错
django.core.exceptions.ImproperlyConfigured: Error loading MySQLdb module.
Did you install mysqlclient?
解决办法:
需要到你的项目同名的文件夹下的__init__.py文件中添加如下代码
import pymysql
pymysql.install_as_MySQLdb()
登陆数据库管理系统,可以看到已经生成数据表myapp_group
说明:1)Django生成数据表时,灰吧models.py的类名转换为小写,然后在前面加上应用程序的名称和下划线作为数据表名称如 myapp.group
2)myapp.group数据表中由id,group_name,group_script 等三个字段,多出的id字段是自动添加的
他作为myapp.group数据表的主键使用
查看生成的数据库表
先切换数据库,再输入命令
use test_orm;
desc myapp_group;
Django ORM 字段在models.py中创建,按照固定格式在数据模型类中建立,主要包括指定字段名的字段类型,字段属性等;
例子:代码
group_name=models.CharField(max_length=32,verbose_name='团体名称')
中的CharFiled是字段类型,知名该字段为字符型,括号内是设置字段属性的参数
常用字段类型
注意:
verbose_name在Django Admin管理后台是字段显示名称,可理解为字段别名,verbose_name在SQL层面没有具体体现,也就是说加不加verbose_name对数据库中的字段没有影响。
主要通过数据模型的objects属性来提供数据操作的接口
1)以下五个函数的返回值都是QuerySet对象集
提示:
django的QuerySet对象集本质上对应于数据库表的记录集合,QuerySet有一个特性就是惰性,及返回值为QuerySet的函数不会立即去数据库操作数据,当我们用到QuerySet的值时,他才回去数据库中获取数据。
2)以下三个函数返回其他数据类型,可以理解为特殊的QuerySet类型。
①先建立一个test_orm项目
django-admin startproject test_orm
使用cd进入该目录
cd test_orm
②输入命令生成一个名称为employee的应用程序
python manage.py startapp employee
③登录Mysql数据库,创建数据库
create database test_orm;
④如果没有安装pymysql模块,在命令行终端数如pip install pymysql进行安装
然后再/test_orm/test_orm/_init_.py文件下输入代码,使用pymysql模块来代替Django Mysql客户端模块
import pymysql
pymysql.install_as_MySQLdb()
⑤在settings中修改配置
注册app
配置数据库
⑥在employee/models.py中输入数据模型代码
from django.db import models
#在此处
# Create your models here.
class employee(models.Model):#员工数据模型(员工数据表)
name=models.CharField(max_length=32,verbose_name='姓名') #员工姓名
email=models.EmailField(verbose_name='邮箱')#员工的邮箱
dep=models.ForeignKey(to="department",to_field="id",on_delete=models.CASCADE) #员工的部门,外键,形成一对多的关系
group=models.ManyToManyField(to="group")#员工加入的团体,多对多关系,就是一个员工可以加入多个团体,一个团体有多个员工
salary=models.DecimalField(max_digits=8,decimal_places=2)#薪水,数值型
info = models.OneToOneField(to='employeeinfo',on_delete=models.CASCADE,null=True)#员工补充信息,一对一关系
class department(models.Model):# 部让数据模型(部门数据表)
dep_name=models.CharField(max_length=32,verbose_name='部门名称',unique=True,blank=False)#部门名称
dep_script=models.CharField(max_length=60,verbose_name='备注',null=True) #部门备注说明
class group(models.Model):#团体数据模型(团体数据表)
group_name=models.CharField(max_length=32,verbose_name='团体名称',unique=True,blank=False) # 团体名称
group_script=models.CharField(max_length=60,verbose_name='备注',null=True) #团体备注说明
class employeeinfo(models.Model): #员工补充信息
phone = models.CharField(max_length=11) #电话号码
address = models.CharField(max_length=50)#地址
解释:
①以上代码生成四个数据模型
②一个部门可以有多个员工,所以在员工表中建立外键(ForeignKey)dep字段。要注意的是,有外键的是’多‘,外键关联的表是’-‘,也就是有外键的数据库表有多条记录对应外键关联的数据库表的一条记录;数据模型中的外键在数据库表中以是 外键名_id 形式命名字段,例如:数据模型employee中的dep,在数据库表中字段名为dep_id。
③一个员工可以加入多个团体,一个团体可以有多个员工,所以在员工表建立了多对多键(ManyToManyField)group字段
④一个员工对应一条补充信息,所以在员工表中建立一对一键(OneToOneField)info字段,info在数据库表中的字段名为info_id
⑦在mysql的test_orm数据库中生成数据表
第一行命令对数据模型代码进行检查,出错时在命令行返回相关信息
第二行真正建立数据表
python manage.py makemigrations
python manage.py migrate
随机查看一个数据表,例如
use test_orm;
desc employee_employee;
Django是在urls.py中设立路由(URL)与视图函数的对应关系。用户在浏览器地址栏中输入网址,Django通过URL配置关系找到对应函数,这个函数接受请求,运行其中的逻辑代码并生成响应发挥浏览器,从而完后曾以此用户业务访问过程。
在/test_orm/urls.py下输入以下代码:
from django.contrib import admin
#导入URL配置相关的模块
from django.urls import path,include
urlpatterns = [
path('admin/', admin.site.urls),
#用include()函数把二级配置包含起来
path('test_orm_old/',include('employee.urls')),
]
说明:
1)include()函数中的参数是一个字符串,这个字符串指定二级URL配置文件的位置,与文件的路径有点相似,只不过用 “."作为分隔符,并且最后的文件名不包含扩展名
2)如果URL配置文件分级,那么在匹配URL时,要把各级配置文件中的URL表达式合并成一个完整的URL表达式进行匹配
在/test_rom/employee 文件夹新建一个urls.py文件
from django.urls import path,include
from employee.views import * #导入视图中的函数,*代表所有
urlpatterns = [
path('list_employee_old/',list_employee_old),
path('add_employee_old/',add_employee_old),
path('edit_employee_old//',edit_employee_old),
path('del_employee_old//',delete_employee_old),
path('add_dep_old/',add_dep_old),
path('list_dep_old/',list_dep_old),
path('del_dep_old//',del_dep_old),
path('edit_dep_old//',edit_dep_old),
path('add_group_old/',add_group_old),
path('list_group_old/',list_group_old),
path('del_group_old//',del_group_old),
path('edit_group_old//',edit_group_old),
path('add_employeeinfo_old/', add_employeeinfo_old),#增加一条用户补充信息(employeeinfo表)
path('list_employeeinfo_old/', list_employeeinfo_old),#用户补充信息列表(employeeinfo表)
path('del_employeeinfo_old//', del_employeeinfo_old),#删除一条用户补充信息(employeeinfo表)
path('edit_employeeinfo_old//', edit_employeeinfo_old),#修改一条用户补充信息(employeeinfo表)
]
说明:
①以上代码分别建立了员工,部门,团体,员工补充信息的增删改查配置项。path()的两个参数中一个用来匹配路径,被称作URL表达式,他撇皮网址的方式类似于正则表达式;
另外一个参数是试图函数名,属兔函数在views.py中定义
②我们在配置项中的URL表带始终和视图函数名后都加了_old,因为这是代码的初始版本,旨在讲解Django ORM的内容,没有对页面进行美化,后续有其他的美化
提示:
在urls.py文件中通过path()建立对应关系后,还需建立相应的视图函数,函数名与path()的第二个参数相同。
打开employee下的views.py文件,编写视图函数:
第一段代码对部门数据表department进行列表查询
from django.shortcuts import render,redirect,HttpResponse
from .models import employee,department,group,employeeinfo
# Create your views here.
#部门数据表的增删改查
def list_dep_old(request):
dep_list=department.objects.all()
return render(request,'test_orm_old/list_dep_old.html',{'dep_list':dep_list})
代码说明:
下面是list_dep_old.html文件的代码,存放在/test_orm/templates/test_orm_old文件夹中
提示:注意创建文件夹
部门列表
代码说明:
下面测试一下效果,在命令行终端,进入根目录test_orm
python manage.py runserver
在地址栏输入https://127.0.0.1:8000/test_orm_old/list_dep_old/并回车
增加部门视图函数add_dep_old()
def add_dep_old(request):
#判断请求方式,如果是POST,说明前端页面要提交数据
if request.method=='POST':
dep_name=request.POST.get('dep_name')
dep_script = request.POST.get('dep_script')
if dep_name.strip()=='':
return render(request, 'test_orm_old/add_dep_old.html', {'error_info': '部门名称不能为空!'})
try:
#用create函数新建一条记录,这条记录会自动保存,不用调用save函数
p=department.objects.create(dep_name=dep_name,dep_script=dep_script)
#重定向
return redirect('/test_orm_old/list_dep_old/')
except Exception as e:
return render(request, 'test_orm_old/add_dep_old.html',{'error_info':'录入部门名称重复或信息有错误!'})
finally:
pass
return render(request,'test_orm_old/add_dep_old.html')
代码说明:
add_dep_old.html
增加部门
增加部门
#当单机保存按钮时,向后端发送post请求
{{ error_info }}
下面是删除部门记录的视图函数,根据传参,获取id字段等于参数值的激励对象爱国,然后删除。视图函数del_dep_old()的第二个参数实在urls.py文件配置项的path函数中定义的
view.py添加
def del_dep_old(request,dep_id):
dep_object=department.objects.get(id=dep_id)
dep_object.delete()
return redirect('/test_orm_old/list_dep_old/')
def edit_dep_old(request,dep_id):
if request.method=='POST':
id=request.POST.get('id')
#获得前端页面提交的数据
dep_name=request.POST.get('dep_name')
dep_script=request.POST.get('dep_script')
dep_object=department.objects.get(id=id)
#给字段赋值
dep_object.dep_name=dep_name
dep_object.dep_script=dep_script
#保存到数据库
dep_object.save()
return redirect('/test_orm_old/list_dep_old/')
else:
dep_object=department.objects.get(id=dep_id)
return render(request,'test_orm_old/edit_dep_old.html',{'department':dep_object})
视图函数edit_dep_old通过return render(request,'test_orm_old/edit_dep_old.html',{'department':dep_object})传递参数给edit_dep_old.html文件
修改部门
修改部门
{{ error_info }}
代码说明:
下面给出group团体数据库增删改查视图函数代码,供参考
#团队增删改查
def list_group_old(request):
group_list=group.objects.all()
return render(request,'test_orm_old/list_group_old.html',{'group_list':group_list})
def add_group_old(request):
if request.method=='POST':
group_name=request.POST.get('group_name')
group_script = request.POST.get('group_script')
if group_name.strip()=='':
return render(request, 'test_orm_old/add_group.html', {'error_info': '团队名称不能为空!'})
try:
group.objects.create(group_name=group_name,group_script=group_script)
return redirect('/test_orm_old/list_group_old/')
except Exception as e:
return render(request, 'test_orm_old/add_group_old.html',{'error_info':'录入团队名称重复或信息有错误!'})
finally:
pass
return render(request, 'test_orm_old/add_group_old.html')
def del_group_old(request,group_id):
group_object=group.objects.get(id=group_id)
group_object.delete()
return redirect('/test_orm_old/list_group_old/')
def edit_group_old(request,group_id):
if request.method=='POST':
id=request.POST.get('id')
group_name=request.POST.get('group_name')
group_script=request.POST.get('group_script')
group_object=group.objects.get(id=id)
group_object.group_name=group_name
group_object.group_script=group_script
group_object.save()
return redirect('/test_orm_old/list_group_old/')
else:
group_object=group.objects.get(id=group_id)
return render(request,'test_orm_old/edit_group_old.html',{'group':group_object})
list_group_old.html
团队列表
add_group_old.html
增加团队
增加团队
{{ error_info }}
edit_group_old.html
#提示