文章目录
一、ORM 对象关系映射
1.原理
Django鼓励开发人员进行相对独立的模块开发,这种开发模式在工作中被称为:解耦合,就是指在开发中将项目看成几个独立的模块进行开发,降低模块之间的耦合性。在这种思路下,django数据开发采用了mvc和mvt设计模式,和ORM机制
- orm将数据库中的表名映射为类名,将字段映射为属性,可以操作类方法,类属性快速操作数据库
- orm可以使用我们创建好的模型,帮我们创建表,无需关心具体使用的是那种数据库
2.创建模型
在models.py创建模型
3. 检查(不常用)
在数据迁移之前,确定配置是否完成
python manage.py check
4.同步表结构和数据迁移
同步表结构
python manage.py makemigrations
数据迁移
python manage.py migrate
这个时候就能看到sqlite3数据库生效了
但是我们注意到表名是自建的,我们修改一下
二、ORM字段类型
1.字段类型
关于字段类型基本上和数据库字段类型相同
类型 | 含义 |
---|---|
CharField | varchar类型,需要指定长度 |
IntegerField | 整型 |
DecimalField | 浮点型,需要指定最大长度和小数点位数 |
DateField | 日期,例如datetime |
ImageField | 图片 |
ForeignKey | 做外键 |
而ForeignKey 做外键又有以下几个参数
①to 设置关联表
②to_field 关联表要关联的键名,默认为关联表中的id,可以不写
③on_delete 当删除关联表中的数据的时候,从表做什么行为,
(1)CASCADE 当关联表中数据删除的时候,外键所在表中的数据也会被删除
(2)SET_NULL 当关联表中数据删除的时候,外键所在表中的外键设置为空
(3)SET_DEFAULT 当关联表中数据删除的时候,外键所在表中的外键设置一个默认值
(4)PROTECT 关联保护,当关联表的数据被删除的时候,报异常,
(5)DO_NOTHING 当关联表中数据删除的时候,外键所在的表不做任何事情
2.字段属性
属性 | 备注 |
---|---|
max_length | 最大长度 |
verbose_name | 备注,站点管理中用于显示字段为中文 |
max_digits | 浮点型最大长度 |
decimal_places | 小数点位数 |
auto_now= True | 获取的是当前时间 |
null= True | 可为空,默认是不为空 |
3.元数据
属性 | 备注 |
---|---|
db_table | 修改表的名字长度 |
verbose_name | 备注,站点管理中用于显示模型名字为中文,会出现s |
verbose_name_plural | 显示复数名称(站点管理处) |
ordering= [‘-age’] | 指定排序 |
三、ORM的单表操作
准备工作:我们重新在models中创建一个类并进行数据迁移
from django.db import models
# 创建学生表
class Person(models.Model):
# id = models.AutoField(primary_key=True)
name = models.CharField(max_length=32, verbose_name='名字')
age = models.IntegerField(verbose_name='年龄')
height = models.DecimalField(max_digits=5, decimal_places=2, verbose_name='身高', null=True) # 长度为5,两位小数
birthday = models.DateField(verbose_name='生日')
def __str__(self):
return self.name
class Meta:
db_table = 'person'
verbose_name = '用户'
verbose_name_plural = verbose_name # 显示的是后台模块的名字
1.添加数据
方法 | 使用 |
---|---|
save | 需要声明model类的对象,然后可以使用对象.属性添加,也可以使用类中声明时候直接添加属性,注意最后需要对象.save()保存 |
create | 借助objects.create(属性1,属性2)添加 |
使用
运行
数据库生效
2.查询数据
常用查询方法
使用 | 功能 |
---|---|
all() | 查询所有结果 |
filter(**kwargs) | 它包含了与所给筛选条件相匹配的对象 |
get(**kwargs) | 返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。 |
exclude(**kwargs) | 它包含了与所给筛选条件不匹配的对象 |
values(*field) | 返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列model的实例化对象,而是一个可迭代的字典序列 |
values_list(*field) | 它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列 |
order_by(*field) | 对查询结果排序 |
reverse() | 对查询结果反向排序,请注意reverse()通常只能在具有已定义顺序的QuerySet上调用(在model类的Meta中指定ordering或调用order_by()方法) |
distinct() | 从返回结果中剔除重复纪录(如果你查询跨越多个表,可能在计算QuerySet时得到重复的结果。此时可以使用distinct(),注意只有在PostgreSQL中支持按字段去重。) |
count() | 返回数据库中匹配查询(QuerySet)的对象数量。 |
first() | 返回第一条记录 |
last() | 返回最后一条记录 |
exists() | 如果QuerySet包含数据,就返回True,否则返回False |
对于返回多个结果的一般返回QuerySet对象(可迭代对象),这里稍微总结一下
类型 | 备注 |
---|---|
返回QuerySet对象的方法 | all()、filter()、exelude()、order_by()、reverse()、distinct() |
特殊的QuerySet | 1.values() :返回一个可迭代的字典序列 2. values_list() 返回一个可迭代的元祖序列 |
返回具体对象的方法 | get()、first()、last() |
返回布尔值的方法 | exists() |
返回数字的方法 | count() |
使用举例
views.py
def getPerson(request):
# 1.all 方法
# data = models.Person.objects.all()
# print (data)
# print (data[0].name)
# print (data[0].age)
# print (data[0].height)
# for one in data:
# print('生日:', one.birthday)
# print('名字:', one.name)
# --------------------------------------------------------------------
# 2.filter()方法,筛选条件,但是返回的是一个queryset类型
# data = models.Person.objects.filter(birthday='1912-12-22')
# for i in data:
# print(i.age)
# -----------------------------------------------------------------------
# 3.exclude()方法和filter方法相反,返回的是非符合条件的
# data = models.Person.objects.exclude(birthday='1912-12-22')
# for i in data:
# print(i.name)
# --------------------------------------------------------------------
# 4.get()方法,筛选条件,一般参数为主键,只能筛选唯一符合条件的
# data=models.Person.objects.get(birthday='1912-12-22')
# print(data)
# --------------------------------------------------------------------
# 5.first()和last()方法,将选出第一条和最后一条数据
# data=models.Person.objects.filter(age=11).first()
# print(data)
# data=models.Person.objects.filter(age=11).last()
# print(data)
# --------------------------------------------------------------------
# 6.order_by 排序,默认升序,降序在参数前加-
# data=models.Person.objects.order_by('-age')
# for i in data:
# print(i.name)
# ---------------------------------------------------------------------
# 7.values,会将查询到的对象以字典形式将详细数据查询出来,并放在列表中
# data=models.Person.objects.all().values()
# print(data)
# ---------------------------------------------------------------
# 8.exists(),查询符合条件的数据是否存在,返回true或false
# data=models.Person.objects.filter(age=33).exists()
# print(data)
# -----------------------------------------------------------------
# 9.count()记录符合条件的条数
# data=models.Person.objects.all().count()
# print(data)
然后还有其他的双下划线查询方法
下划线查询法 | 用法 |
---|---|
__gt | > |
__lt | < |
__gte | ≥ |
__lte | ≤ |
__in | 包含 |
__range | 范围 |
__isnull | 为空 |
startswitch | 开始,类似 like ‘a%’ |
endswitch | 结束,类似 like ‘%a’ |
contains | 类似 %a% ,对大小写敏感 |
icontains | 类似 %a% ,对大小写不敏感 |
举例用法:
def getPerson(request):
#__gt大于 __lt小于 __gte大于等于 __lte 小于等于
# data=models.Person.objects.filter(age__gt=20)
# print(data[0].name)
# ---------------------------------------------------------
#__in包含,exclude不包含,range范围
# data=models.Person.objects.filter(age__in=(22,))
# for i in data:
# print(i.name)
# data = models.Person.objects.exclude(age__in=(22,))
# for i in data:
# print(i.name)
# data=models.Person.objects.filter(age__range=(15,30))
# for i in data:
# print(i.name)
# ---------------------------------------------------------
# 查询身高为__isnull
# data=models.Person.objects.filter(height__isnull=True)
# for i in data:
# i.height=1.11
# i.save()
# ---------------------------------------------------------
#查询开头的startswitch和查询结尾的endswitch
# data=models.Person.objects.filter(name__startswith='讲师')#like '讲师%'
# print(data[0].name)
# data=models.Person.objects.filter(name__endswith='罗')
# print(data[0].name)
# ---------------------------------------------------------
#包含的contains类似like %a% 对大小写敏感 icontains 对大小写不敏感
data=models.Person.objects.filter(name__contains='师')
print(data[0].name)
return HttpResponse('查询数据成功')
3.修改数据
views.py
def updatePerson(request):
#1.save(),先查要修改的数据,然后直接用对象.属性=修改值,如果查询的数据为多个需要用遍历修改
# data=models.Person.objects.get(id=2)
# data.height=233.34
# data.save()
#--------------------------------------------------------------
#2.update(),先查后更新
models.Person.objects.filter(id=3).update(name='孙悟空') # 更新什么写什么字段
return HttpResponse('修改数据成功')
4.删除数据
views.py
def delPerson(request):
models.Person.objects.get(id=6).delete()
return HttpResponse('删除数据成功')
四、多表查询(一对多)
准备工作:创建多表,并进行数据迁移
models.py
1.增加数据
views.py
# 方法1--------------------------------------------------
# 增加出版社
# Publish.objects.create(name='清华出版社',address = '北京')
# Publish.objects.create(name='中国出版社',address = '北京朝阳')
# Publish.objects.create(name='河南出版社',address = '洛阳')
# 增加书
# Book.objects.create(name='python入门',publish_id = 1)
# 将出版社和书关联
# publish = Publish.objects.get(name='中国出版社')
# Book.objects.create(name='python入门', publish_id=publish.id)
# 方法2--------------------------------------------------
# Book.objects.create(name='python核心编程',publish = Publish.objects.get(name='中国出版社'))
# 方法3--------------------------------------------------
# 正向操作 从外键所在的表到主表叫正向
book = Book()
book.name= '笨办法学python'
book.publish = Publish.objects.get(name='河南出版社')
book.save()
# 反向操作 从主表到从表 叫反向
publish_obj = Publish.objects.get(name="中国出版社")
publish_obj.book_set.create(name='pythonWeb开发')
2.查询数据
views.py
# 方法1--------------------------------------------------
# publish = Publish.objects.get(name="中国出版社")
# book = Book.objects.filter(publish_id=publish.id).all()
# for x in book:
# print (x.name)
# 方法2--------------------------------------------------
# 正向查询 从外键所在的表到主表叫正向
# 查询 pythonWeb开发 属于哪一个出版社
# book = Book.objects.filter(name='pythonWeb开发').first()
# print (book.name)
# print (book.publish.name)
# 方法3--------------------------------------------------
# 反向查询 从主表到从表 叫 反向查询 _set
publish = Publish.objects.get(name='中国出版社')
book = publish.book_set.all()
print (book)
3.更新数据
views.py
# 一对多更新数据
def updatemore(request):
# save
# book=models.Book.objects.get(id=2)
# book.publish=models.Publish.objects.get(name='清华出版社')
# book.save()
# #upadate
# models.Book.objects.update(name='python',publish=models.Publish.objects.get(id=3))
#set
# 反向,类似数据库中的update
publish = models.Publish.objects.get(name='蓝翔出版社')
book = models.Book.objects.get(id=2)
book2 = models.Book.objects.get(id=1)
publish.book_set.set([book, book2])
return HttpResponse('修改数据成功')
4.删除数据
views.py
# 一对多删除数据
def delmore(request):
# 一般先删除从表再删除主表,根据模型类里的外键设置决定
models.Book.get(id=2).delete()
models.Publish.get(id=2).delete()
return HttpResponse('删除数据成功')
五、多表查询(多对多关系)
准备工作:建表+数据迁移
models.py
class Person(models.Model):
# id = models.AutoField(primary_key=True)
name = models.CharField(max_length=32,verbose_name="姓名")
age = models.IntegerField(verbose_name="年龄")
height = models.DecimalField(max_digits=5,decimal_places=2,verbose_name="身高",null=True)
birthday = models.DateField(verbose_name="生日",auto_now=True)
def __str__(self):
return str(self.name)
class Meta:
db_table = 'person'
verbose_name = "用户"
verbose_name_plural = verbose_name
# ordering= ['-age','id','name']
class Teacher(models.Model):
name = models.CharField(max_length=32)
age = models.IntegerField(default=0)
gender = models.CharField(max_length=8)
person = models.ManyToManyField(to=Person)
class Meta:
db_table = 'teacher'
1.添加数据
views.py
# 多对多添加
def addmanytomany(request):
# 添加老师
# models.Teacher.objects.create(name='僵尸王宗涛',gender=1)
# models.Teacher.objects.create(name='僵尸张环宇',gender=0)
# models.Teacher.objects.create(name='僵尸温俊鹏',gender=1)
# 正向操作
# 添加新学生,和僵尸王宗涛关联
# teacher=models.Teacher.objects.get(name='僵尸王宗涛')
# teacher.person.create(name='孙悟空',age=3)
# 老学生关联温老师,需要将两个数据都查出来,并使用add()
# teacher=models.Teacher.objects.get(id=3)
# person=models.Person.objects.filter(name='泰罗').first()
# teacher.person.add(person)
# 反向操作
teacher = models.Teacher.objects.get(id=2)
person = models.Person.objects.get(id=1)
person.teacher_set.add(teacher)
return HttpResponse('添加成功')
2.查询数据
views.py
# 多对多查询
def getmanytomany(request):
# 寻找id为3的老师教的所有学生
teacher = models.Teacher.objects.get(id=3)
person = teacher.person.all()
print(person.values())
# 根据学生查老师
person = models.Person.objects.get(id=6)
teacher = person.teacher_set.all()
print(teacher.values())
return HttpResponse('查询成功')
3.修改数据
# 多对多修改
def updatemanytomany(request):
# 正向修改
# 将讲师王宗涛的学生改为234,set后边放列表,列表里传入更改的关联数据
# teacher=models.Teacher.objects.get(id=1)
# person1=models.Teacher.objects.get(id=2)
# person2=models.Teacher.objects.get(id=3)
# person3=models.Teacher.objects.get(id=4)
# teacher.person.set([person1,person2,person3])
# 反向
person = models.Person.objects.get(id=2)
teacher1 = models.Teacher.objects.get(id=3)
teacher2 = models.Teacher.objects.get(id=2)
person.teacher_set.set([teacher1, teacher2])
return HttpResponse('修改成功')
4.删除数据
# 多对多删除
def delmanytomany(request):
# remove 解除关系
# 正向
# teacher=models.Teacher.objects.get(id=1)
# person=models.Person.objects.get(id=3)
# teacher.person.remove(person)
# 反向
# person=models.Person.objects.get(id=4)
# teacher=models.Teacher.objects.get(id=1)
# person.teacher_set.remove(teacher)
# del删除
models.Person.objects.get(id=2).delete()
return HttpResponse('删除成功')
六、聚合函数和F/Q对象
1.聚合函数
求点最大值最小值平均值什么的
# 聚合函数
from django.db.models import Max, Min, Count, Avg, Sum
def juhe(request):
data = models.Person.objects.all().aggregate(Avg('age'))
print(data) # 显示的是queryset
data = models.Person.objects.all().aggregate(Avg('age'), sum('age'))
print(data) # 显示的是queryset
return HttpResponse('聚合查询')
2.F对象和Q对象
- F对象: 用于比较同一个模型中的两个字段的值
- Q对象:用于处理多条件中的逻辑关系 and or not
from django.db.models import F, Q
def Ftest(request):
# 查询book中销量大于库存的
book = models.Book.objects.filter(xiaoliang__gt=F('kucun')).all()
print(book)
return HttpResponse('f对象')
def Qtest(request):
# and
book = models.Book.objects.filter(Q(xiaoliang=20) & Q(kucun=50))
print(book)
book = models.Book.objects.filter(xiaoliang=20, kucun=50)
print(book)
# or
book = models.Book.objects.filter(Q(xiaoliang=20) | Q(kucun=50))
print(book)
# not
book = models.Book.objects.filter(~Q(xiaoliang=20) | ~Q(kucun=50))
print(book)
return HttpResponse('q对象')
七、后台站点管理
1.命令行输入创建超级用户,并输入用户名和邮箱和密码
python manage.py createsuperuser
2.进入后台站点
运行项目,地址加入admin
3.安装模型类
在创建的类中将类名传入admin
4.使用后台管理可以管理数据
5.修改站点管理后台为中文