Django模型层
Django中内嵌啦ORM框架,不需要直接编写SQL语句金喜数据库操作,而是通过定义模型类,操作模型类来完成对数据库中表的增删该查
ORM(object,relation,mapping)
O是object,也就****类对象的意思。
R是relation,翻译成中文是关系,也就是关系数据库中****数据表的意思。
M是mapping,是****映射的意思。
类:sql语句table表
类成员变量:table表中的字段、类型和约束
类对象:sql表的表记录
可以通过以下操作对Django的数据库操作
1.配置数据库连接信息
2.在models.py中定义模型类
3.生成数据库迁移文件并执行迁移文件[注意:数据迁移是一个独立的功能,这个功能在其他web框架未必和ORM一块]
4.通过模型类对象提供的方法或属性完成数据表的增删改查
配置数据库连接
在settings.py中保存啦数据库的连接配置信息,Django默认初始配置使用sqlite数据库
使用mysql前需要先安装驱动程序,官方推荐使用mysqlclient,我们这里介绍pymysql和mysqlclient
#首先介绍pymysql,在任意的Django项目中的init文件中导入pymysql
from pymysql import install_as_MySQLdb
install_as_MySQLdb() #这样写是相当于猴子补丁,把orm默认使用的数据库连接替换了pymysql
#mysqlclient #官方推荐
在ubuntu安装mysqlclient
sudo apt install libmysqlclient-dev python3-dev
pip install mysqlclient
#然后接下来在settings文件中配置数据库连接
DATABASES={
’default‘:’django.db.backends.mysql‘,
'HOST1': ’ip地址‘,
’PORT‘:3306,#端口号,如果你改了端口这里也需要改
‘USER’:‘用户’,
‘password’:‘密码’,
‘NAME’:‘库名称’,#连接那个数据库
‘CHARSET’:‘编码格式’,#utf8 or utf8mb4
}
字段类型
约束选项
注意:null是数据库范畴的概念,blank是表单验证范畴的
makemigrations,migrate的使用
设置公共的模型类,以后生条每条记录都是有时间,可以把这个时间设置为公共类,但是遮盖公共类设置为抽象类,这样就不会和数据库中的表产生映射关系
class Basemodel(models.Model):
create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
update_time = models.DateTimeField(auto_now=True, verbose_name='修改时间')
class Meta(object):
abstract = True # 设置当前模型为抽象类,当系统运行时,就不会认为和数据库有一一映射的关系了
from django.db import models
# Create your models here.
from .Base_model import Basemodel
class Person(Basemodel):
name = models.CharField(max_length=30, verbose_name='username')
pwd = models.CharField(max_length=20, verbose_name='pwd')
gender = models.CharField(max_length=20, verbose_name='性别', default='female')
price = models.DecimalField(max_digits=20, decimal_places=5, verbose_name='价格')
# auto_now_add 当数据添加时,设置当前时间为默认值
# auto_now 当数据添加/更新时,设置当前时间为默认值
class Meta:
# abstract = True # 设置当前模型为抽象模型,当系统运行时,不会认为这是一个数据表对应的模型
db_table = 'tb_person' # 指明数据库表名,如果没有指定表名,则默认为子应用目录名
verbose_name = '人表' # 在admin站点中显示的名称
verbose_name_plural = verbose_name # 显示的复数名称
#注意:一定要在命令行窗口,并且在manage.py目录下运行,下面有详细步骤
python manage.py makemigrations
python manage.py migrate
以下均为测试数据
增加数据
第一种方法:create
def test01(request):
student=Person.objects.create(name='zhangsan',pwd='123',gender='faamle',price='6666',total='8888')
print(student.id)
return HttpResponse('userinfo')
第二种方法:save()
student=Person(
name='wangwu',
pwd='23',
gender='female',
price='123456',
total='6666666',
)
student.save()
print(student.id)
return HttpResponse('userinfo')
查询数据
all() #查询所有对象,返回queryset对象,获取模型类集合
def test01(request):
stu=Person.objects.all()
for i in stu:
print(i.pk)
return HttpResponse('userinfo')
filter() # 筛选条件相匹配的对象,返回queryset对象
def test01(request):
stu=Person.objects.filter(gender='female').filter(pk=1) #支持链式表达式,多个filter合并是and关系
for i in stu:
print(i)
return HttpResponse('userinfo')
get() #返回与所给筛选条件想匹配的对象,返回结果有且只有一个,如果筛选条件的对象超过一个或者没有,都会抛出错误
def test01(request):
stu=Person.objects.get(pk=1,gender='male')
print(stu)
return HttpResponse('userinfo')
first(),last() #返回第一条记录和最后一条记录
def test01(request):
stu = Person.objects.first()
stu1=Person.objects.last()
print(stu,stu1)
return HttpResponse('userinfo')
exists() #判断查询结果中是否有某个数据,有返回True,没有返回False
def test01(request):
res=Demo_db.objects.filter(pk=101).exists()
print(res)
return HttpResponse('userinfo')
exclude() #筛选条件不匹配的对象(除了某个条件之外,返回剩余的),返回queryset对象
def test01(request):
res = Demo_db.objects.exclude(pk=1)
for i in res:
print(i)
print(res)
return HttpResponse('userinfo')
order_by() #对查询结果排序
在查询字段增加减号(-)表示从大到小排序
def test01(request):
res = Demo_db.objects.all().order_by('-age') #从大到小
print(res)
res1 = Demo_db.objects.all().order_by('age')
print(res1) #从
return HttpResponse('userinfo')
count() #统计对象的个数
def test02():
res = Demo_db.objects.filter(sex=1).count()
print(res)
values() #把结果集中的对象转换成字典,列表套字典,可以指定查那些字段,达到减少内存消耗,提高性能
def test02():
res = Demo_db.objects.values('pk','name')
for i in res:
print(i)
values_list() #默认结果是一个个元祖,可以指定需要那些字段
def test02():
res = Demo_db.objects.values_list('pk','name')
for i in res:
print(i)
distinct() #从返回结果中剔除重复记录,返回queryset对象
def test02():
res=Demo_db.objects.values('age').distinct()
print(res)
contains #模糊查询 (双下划线__)
说明:如果包含%无需转意,直接写即可
def test02():
res = Demo_db.objects.filter(name__contains='程') # %程%
print(res)
startwith
def test02():
res = Demo_db.objects.filter(name__startswith='程') # %程
print(res)
endwith
def test02():
res = Demo_db.objects.filter(name__endswith='程') # 程%
print(res)
**以上运算符都区分大小写,在这些运算符前加上i表示不区分大小写,如iexact、icontains、istartswith、iendswith.**
def test02():
res = Person.objects.filter(gender__icontains='MALE')
print(res)
in
def test02():
res = Person.objects.filter(id__in=[1,3,5])
print(res)
range #范围查询
def test02():
res = Demo_db.objects.filter(pk__range=(1,10))
print(res)
模糊查询之比较查询
def test02():
res = Demo_db.objects.filter(pk__gt=3) #大于
res1=Demo_db.objects.filter(pk__gte=10) #大于等于
res2=Demo_db.objects.filter(pk__lt=10) #小于
res3=Demo_db.objects.filter(pk__lte=10) #小于等于10
print(res)
print(res1)
print(res2)
print(res3)
模糊查询之日期查询
**year、month、day、week_day、hour、minute、second:对日期时间类型的属性进行运算。
def test02():
res=Demo_db.objects.filter(create_time__year=2021).values_list()
res1=Demo_db.objects.filter(create_time__month=8).values('id','name')
res2=Demo_db.objects.filter(create_time__day=20).count()
print(res)
print(res1)
print(res2)
Q查询 #多个过滤器逐个调用逻辑与关系没,同sql语句中where部分的and关键字
例如:查询年龄大于20,并且编号小于30的学生
def test02():
res=Demo_db.objects.filter(Q(Q(age__gt=20) & Q(pk__lt=30)))
print(res)
def test02():
# res=Demo_db.objects.filter(Q(Q(age__gt=20) & Q(pk__lt=30)))
# res = Person.objects.filter(Q(Q(price__gt=10000) | Q(gender='male')))
res = Demo_db.objects.filter(Q(Q(age__lt=19) | Q(age__gt=20))).all()
print(res)
Q对象左边可以使用~操作符,表示非not。
def test02():
res = Person.objects.filter(~Q(pk=5))
print(res)
F #查询
两个字段的值比较,更新,过滤字段
def test02():
res = Demo_db.objects.filter(pk=1).update(age=F('age') + 10, create_time=F('create_time'))
print(res)
聚合查询
raw:执行原生SQL语句
执行原生SQL返回一个对象:<RawQuerySet: select * from test_tb where age > 20>
def test02():
res=Demo_db.objects.raw('select * from test_tb where age > %s',(20,))
for i in res:
print(i)
print(res)
使用aggregate()过滤器调用聚合函数,聚合函数包括:
Avg:平均
Count:数量
Max:最大
Min:最小
Sum:求和
ps:
def test02():
# res1 = Person.objects.aggregate(total_avg=Avg('total'))
# res=Person.objects.aggregate(my_sum=Sum('price'))
res2 = Demo_db.objects.aggregate(my_age=Max('age'))
res3 = Demo_db.objects.aggregate(my_age=Min('age'))
res4 = Demo_db.objects.aggregate(my_pk=Count('pk'))
print(res2)
print(res3)
print(res4)
修改记录
save() #修改 性能查,不推荐使用
def test02():
res = Person.objects.first()
res.gender = 'male'
res.save()
print(res)
update() #修改,推荐使用,基于queryset对象,返回影响的行数
#使用时请务必加上条件,否则影响的是全局,亲测
def test02():
#
# res = Person.objects.filter(pk=1).update(name='tany')
res1 = Person.objects.filter(pk=2).update(
name='tank',
pwd=123,
gender='male',
price=66,
total=10000,
)
print(res1)
删除记录
!删除记录时一定要加上条件,否则就变成清空表了
def test02():
res=Demo_db.objects.filter().delete() #清空表,谨慎操作
print(res)
delete #有两种方法
def test02():
res = Person.objects.filter(pk=1).delete() #返回一个元组,第一个可以理解为删除的记录数,第二个是影响的函数
print(res)
#下面这种方式删除返回删除记录的名字
def test02():
res = Person.objects.get(pk=2)
res.delete()
print(res)
创建关联关系
在设置外键时,需要通过on_delete选项指明主表删除数据时,对于外键引用表数据如何处理,在django.db.models中包含类可选常量:
CASCADE #级联,删除主表数据时连通一起删除外键表中数据
PROTECT #保护,通过抛出***ProtectedError异常,来阻止删除主表中被外键应用的数据
SET_NULL #设置为NULL,近在该字段设置了默认值时可用
SET_DEFAULT #设置为默认值,仅在该字段设置类默认值时可用
SET() #设置特定值或者调用特定方法
一对一(内部的关联关系)
class Employee(Basemodel):
name = models.CharField(max_length=32, verbose_name='公司部门')
address = models.CharField(max_length=100, verbose_name='公司地址')
parent = models.ForeignKey('self', on_delete=models.SET_NULL, null=True, verbose_name='所属部门')
class Meta:
db_table = 'employee'
verbose_name = '部门表'
**一对多**
#正向查询按字段
#反向查询类名小写+_set
class Employee(Basemodel):
name = models.CharField(verbose_name='员工姓名', max_length=20, unique=True)
job = models.CharField(verbose_name='员工职位', max_length=2, choices=Jobchoices.choices, default=Jobchoices.CE)
entry_date = models.DateField(verbose_name='入职日期', default=date.today())
sal = models.IntegerField(verbose_name='薪资级别')
bonus = models.IntegerField(verbose_name='津贴', default=0)
is_leave = models.BooleanField(verbose_name='是否离职', default=False)
# 允许为空,且为空字符
dept = models.ForeignKey('Deptmodel',
verbose_name='员工所属的部门',
on_delete=models.SET_NULL,
null=True,
blank=True)
class Meta:
db_table = 't_emp'
verbose_name = '员工表'
def __str__(self):
return f'当前员工是:{self.name},当前职位是:{self.job}'
class Deptmodel(Basemodel):
name = models.CharField(max_length=32, verbose_name='部门名字')
address = models.CharField(max_length=100, verbose_name='公司地址')
parent = models.ForeignKey('self', on_delete=models.SET_NULL, null=True, verbose_name='所属部门')
class Meta:
db_table = 't_dept'
verbose_name = '部门表'
def __str__(self):
return f'当前的部门是:{self.name}'
一对一 #外键在查询较多的一方
class IDcard(Basemodel):
number = models.CharField(verbose_name='身份证号', max_length=32)
start_time = models.DateField(verbose_name='起始时间', null=True, blank=True)
end_time = models.DateField(verbose_name='结束时间', null=True, blank=True)
class Meta:
db_table = 't_IDcard'
verbose_name = '身份证'
class Employee(Basemodel):
name = models.CharField(verbose_name='员工姓名', max_length=20, unique=True)
job = models.CharField(verbose_name='员工职位', max_length=2, choices=Jobchoices.choices, default=Jobchoices.CE)
entry_date = models.DateField(verbose_name='入职日期', default=date.today())
sal = models.IntegerField(verbose_name='薪资级别')
bonus = models.IntegerField(verbose_name='津贴', default=0)
is_leave = models.BooleanField(verbose_name='是否离职', default=False)
# 允许为空,且为空字符
idcard = models.OneToOneField('IDcard', on_delete=models.CASCADE, null=True, blank=True)
多对多 #总的来说还是一对多或者多对一的情况
class Role(Basemodel):
name = models.CharField(verbose_name='权限的名称', unique=True, max_length=20)
class Meta:
db_table = 't_role'
verbose_name = '权限表'
class Deptmodel(Basemodel):
name = models.CharField(max_length=32, verbose_name='部门名字')
address = models.CharField(max_length=100, verbose_name='公司地址')
parent = models.ForeignKey('self', on_delete=models.SET_NULL, null=True, verbose_name='所属部门')
class Meta:
db_table = 't_dept'
verbose_name = '部门表'
class Employee(Basemodel):
name = models.CharField(verbose_name='员工姓名', max_length=20, unique=True)
job = models.CharField(verbose_name='员工职位', max_length=2, choices=Jobchoices.choices, default=Jobchoices.CE)
entry_date = models.DateField(verbose_name='入职日期', default=date.today())
sal = models.IntegerField(verbose_name='薪资级别')
bonus = models.IntegerField(verbose_name='津贴', default=0)
is_leave = models.BooleanField(verbose_name='是否离职', default=False)
# 允许为空,且为空字符
dept = models.ForeignKey('Deptmodel',
verbose_name='员工所属的部门',
on_delete=models.SET_NULL,
null=True,
blank=True)
idcard = models.OneToOneField('IDcard', on_delete=models.CASCADE, null=True, blank=True)
roles = models.ManyToManyField('Role', verbose_name='权限', related_name='t_emp_role', db_table='t_emp_role',
null=True, blank=True)
# r1 = Role.objects.create(name='销售人员')
# r2 = Role.objects.create(name='出库人员')
# r1 = Role.objects.create(name='财务人员')
emp = Employee.objects.get(pk=8)
emp1 = Employee.objects.get(pk=7)
r1 = Role.objects.get(pk=1)
r2 = Role.objects.get(pk=2)
r3 = Role.objects.get(pk=3)
# 正向查询按字段
# emp.roles.add(r1, r2, r3) # 给员工为1增加权限销售人员,一个员工拥有多个权限
# emp.save()
r1.t_emp_role.add(emp, emp1) # 多个员工拥有一个权限
r1.save()
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)