模型3
模型
一、数据库概述与配置
1、ORM
- 概述
中文为对象关系映射
Django提供了各种数据库的支持 为大多数数据库提供了统一的接口 以方便请求大多数数据库 - 作用
通过ORM可以使用类的方式进行操作数据库 而不用再写原生SQL - 任务
根据对象的类型生成表结构
将对象的操作转换为SQL语句 - 优点
易用性:使用ORM做数据库的开发 可以有效的减少重复SQL的概率 写出来的模型也会更加直观清晰
性能损耗小 : ORM进行底层转化会有一定开销 但是总体来看 好处大于消耗的
设计灵活:可以写出复杂的查询
可移植性:底层封装了对数据库的实现 支持多个关系的数据库引擎 所以可以非常轻松的更改数据库
2、数据库配置
- 默认配置
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
} - MySQL连接
settings.py
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'day40django',
'HOST': '127.0.0.1',
'PORT': '3306',
'USER': 'root',
'PASSWORD': '123456',
}
}- 安装mysql扩展库
pip install pymysql - project/init
import pymysql
pymysql.install_as_MySQLdb()
- 安装mysql扩展库
3、表分析
- 需求
创建用户表 - 所需字段
id 用户名 密码 性别 年龄 个人简介 头像 是否删除 注册时间
二、定义模型
1、字段类型
字段名称 字段说明 参数
AutoField 一个根据实际id进行自动增长的inter field(默认创建的) primary_key = True
CharField varchar类型字段 max_length 存储值最大长度
TextField longtext 长文本
IntegerField int类型字段 存储整形
SmallInterField 小整数 -32768-32767
DecimalField 存储浮点型 更加精准 max_digits=None 位数长度decimal_places=None 小数的位数
FloatField 浮点型
BooleanField 存储bool值 True/False
NullBooleanField 存储Null/True/False
DateField date字段 auto_now=False 如果对数据进行修改则会自动保存修改时间
auto_now_add=False 会自动添加第一次保存的时间 俩个不同同时设定
TimeField time字段 同上
DateTimeField datetimefield字段 同上
FileField 文件上传 upload_to = '' 文件上传保存的路径
ImageField 图片上传字段(继承了FileField 对图像进行了验证 确保是一个有效的图片) 同上
2、字段选项
通过字段选项 可以实现对字段约束 在字段对象使用关键字参数进行指定
选项 说明
null 如果设置为True 则当前字段可以为null
blank 如果设置为True 则当前字段可以什么值都没有 设置在字符串类型的字段上
db_column 设置字段名称 如果不设置 默认为属性名
db_index 设置为True 常规索引
unique 设置为True 唯一索引
primary_key 设置为True 主键索引
default 默认值
3、模型创建
models.py
from django.db import models
# Create your models here.
class User(models.Model):
# 用户名
username = models.CharField(max_length=12)
# 密码
userpass = models.CharField(max_length=64)
# 性别
sex = models.BooleanField(default=True)
# 年龄
age = models.SmallIntegerField(default=18)
# 个人简介
info = models.CharField(max_length=200, default='个人简介')
# 头像
icon = models.CharField(max_length=60, default='default.jpg')
# 是否删除
isDelete = models.BooleanField(default=False)
# 注册时间
registerTime = models.DateTimeField(auto_now_add=True)
4、迁移到数据库中
- 生成迁移文件
python manage.py makemigrations - 迁移到数据库中
python manage.py migrate - 注意
表名默认为 应用名_类名 全都小写
app_user
5、关系
- 一对一
- 一对多
- 多对多
6、元选项
- 作用
在模型类中使用Meta类设置一些信息 - 实例
class User(models.Model):
...
registerTime = models.DateTimeField(auto_now_add=True)
class Meta:
db_table = 'user' # 更改表名称为user
# ordering = ['-age', 'id'] # 按照年龄降序 如果年龄相同 id升序
ordering = ['-age'] # 按照年龄降序
7、数据测试
-
数据添加
# 保存数据(数据添加)
def save(req):
u = User()
u.username = 'lucky'
u.userpass = '123456'
u.sex = True
u.age = 18
u.info = 'lucky的个人简介'
u.icon = './lucky.jpg'
u.isDelete = False
u.save()
return HttpResponse('数据添加') -
数据查询
# 查询数据
def select(req):
u = User.objects.all()
print(u)
for o in u:
# print(o.username,'-------',o.userpass)
print(o)
return HttpResponse('数据查询') -
注意
当打印每一个对象的时候 发现数据并不直观因为都是object 更改类 添加str方法 作为友好输出
更改User模型类
from django.db import models# Create your models here. class User(models.Model): # 用户名 username = models.CharField(max_length=12) # 密码 userpass = models.CharField(max_length=64) # 性别 sex = models.BooleanField(default=True) # 年龄 age = models.SmallIntegerField(default=18, db_column='u_age') # 个人简介 info = models.CharField(max_length=200, default='个人简介') # 头像 icon = models.CharField(max_length=60, default='default.jpg') # 是否删除 isDelete = models.BooleanField(default=False) # 注册时间 registerTime = models.DateTimeField(auto_now_add=True) def __str__(self): return self.username class Meta: db_table = 'user' # 更改表名称为user # ordering = ['-age', 'id'] ordering = ['-age'] # 按照年龄降序
8、objects
-
概念
- 是Manager类的对象 用于与数据库进行交互
- 如果定义模型时没有指定objects 则会默认创建objects
-
问题
在查询的时候 好多地方都使用了同一个过滤器 可不可以 把过滤器放到objects中 对原始查询集进行过滤 -
自定义管理器对象
models.py
from django.db import models# 继承模型管理器类 class MyManager(models.Manager): # 重写查询方法 def get_queryset(self): # 重写了父类中的get_queryset方法 并增加了过滤功能 过滤掉isdelete为True的数据 return super().get_queryset().filter(isDelete=False) # return super().get_queryset() # Create your models here. class User(models.Model): # 自定义模型管理器对象 objects = models.Manager() o = models.Manager() # 可以有多个模型管理器 my_obj = MyManager() # 自定义添加过滤功能的模型管理器 ... # 注册时间 registerTime = models.DateTimeField(auto_now_add=True) def __str__(self): return self.username class Meta: db_table = 'user' # 更改表名称为user # ordering = ['-age', 'id'] # ordering = ['-age'] # 按照年龄降序
views.py
def select(req):
# 使用自定义模型管理器
# u = User.objects.all()
# u = User.o.all()# 使用自定义模型管理器并重写了查询方法 # u = User.my_obj.all() # 等同于 u = User.objects.filter(isDelete=False) u = User.objects.filter(isDelete=False) print(u.query) for o in u: # print(o.username,'-------',o.userpass) print(o.isDelete) # u = User.objects # print(u) # print(type(u)) return HttpResponse('数据查询')
三、数据添加
1、创建对象
- 概述
当创建对象以后 使用属性进行赋值 当调用save以后 才与数据库进行交互 - 实例
def save(req):
u = User()
u.username = 'lucky'
u.userpass = '123456'
u.sex = True
u.age = 18
u.info = 'lucky的个人简介'
u.icon = './lucky.jpg'
u.isDelete = False
u.save()
return HttpResponse('数据添加')
2、实例化对象并传参
- 概述
当模型类实例化以后 进行参数传递 - 实例
#数据添加第二种方法
u = User(3, '张三','123456')
u = User(username='李四', userpass='123456')
u.save()
return HttpResponse('数据添加') - 注意
如果不指定参数 id也需要传参
3、create方法
-
使用create方法
# 第三种数据添加方法
User.objects.create(username='王五', userpass='123456')
return HttpResponse('数据添加') -
重写create方法
models.py
class MyManager(models.Manager):
def get_queryset(self):
# 重写了父类中的get_queryset方法 并增加了过滤功能 过滤掉isdelete为True的数据
return super().get_queryset().filter(isDelete=False)
# return super().get_queryset()# 重写create方法 def create(self, username='', userpass='', sex=True,age=18,info='lucky的个人简介', icon='./lucky.jpg', isDelete=False): u = self.model() u.username = username u.userpass = userpass u.sex = sex u.age = age u.info = info u.icon = icon u.isDelete = isDelete return u # Create your models here. class User(models.Model): # 自定义模型管理器对象 objects = models.Manager() # o = models.Manager() my_obj = MyManager() # 用户名 ...
views.py
u = User.my_obj.create('赵六', '123456')
u.save()
4、添加多条数据 bulk_create()
- 概述
批量添加数据
u1 = User(username='秦七', userpass='123456')
u2 = User(username='王老八', userpass='123456')
User.objects.bulk_create([u1, u2])
5、类方法
- 概述
通过classmethod方法进行数据添加 - 实例
models.py
# Create your models here.
class User(models.Model):
# 自定义模型管理器对象
objects = models.Manager()
# o = models.Manager()
my_obj = MyManager()
...
# 类方法用于添加数据
@classmethod
def create(cls, username='', userpass='', sex=True,age=18,info='lucky的个人简介', icon='./lucky.jpg', isDelete=False):
return cls(username=username, userpass=userpass, sex=sex,age=age,info=info, icon=icon, isDelete=isDelete)
views.py
# 第五种 使用类方法
User.create('婷婷', '123456').save()
return HttpResponse('数据添加')
四、查询
1、数据查询名词解析
- 查询集
从数据库中获取数据查询的集合 - 原始查询集
调用get_queryset() 方法查询获取到的数据为原始查询集 不作为数据的提取 - 数据查询集
通过原始查询集配合过滤器等最终得到的数据 - 过滤器
对数据进行筛选
2、返回查询集的过滤器
- all()
概述: 返回所有
def show(req):
u = User.objects.all()
print(u)
return render(req, 'show.html', {'data': u}) - filter()
过滤掉不符合条件的数据
# 查询没有删除的数据和性别为False的数据
u = User.objects.filter(isDelete=False).filter(sex=False)
u = User.objects.filter(isDelete=False, sex=False) - exclude()
过滤掉符合条件的数据
# 过滤掉没有删除的数据和性别为False的数据
u = User.objects.exclude(isDelete=False, sex=False) - order_by()
排序- '字段' 升序
- '-字段' 降序
u = User.objects.order_by('-age')
u = User.objects.order_by('age' ,'-id')
- values()
返回一个列表 每条数据是一个字典- values() 返回所有
- values(field1,[field2....]) 返回指定字段的值
u = User.objects.values()
u = User.objects.values('username')
- extra()
起别名
extra(select={'new': 'old'})
u = User.objects.all().extra(select={'name': 'username'})
print(u[0].name)
3、返回单个值的过滤器
- get()
返回单个满足条件的对象
u = User.objects.get(age=20)
u = User.objects.get(age=18)
u = User.objects.get(age=180)
注意: 只能返回一个值 如果大于小于一个值 都会抛出异常 - count()
放回当前查询集的数据条数
u = User.objects.all().count()
u = User.objects.filter(age=18).count() - first()
返回查询集中的第一个对象
u = User.objects.order_by('-age').first() - last()
最后一个对象
u = User.objects.order_by('-age').last() - exists()
判断筛选后的数据是否存在
u = User.objects.filter(age=18).exists()
u = User.objects.filter(age=180).exists() - values_list()
将模型对象转换成列表 达到减少内存损耗 提高性能
u = User.objects.values_list()
4、字段查询
- 概述
实现where子句 filter、exclude等参数 - 语法
属性名__比较运算符=值 - 更改表结构 查询区分大小写
alter table user modify username varchar(20) collate utf8_bin not null;
alter table user modify username varchar(20) character set utf8 not null; - exact()
表示判等 不区分大小写
u = User.objects.filter(username__exact='lucky')
u = User.objects.filter(username='lucky') - contains
包含 (区分大小写)
u = User.objects.filter(username__contains='l')
u = User.objects.filter(username__contains='L')
不区分大小写
u = User.objects.filter(username__icontains='l') - startswith
以...开头 (区分大小写)
u = User.objects.filter(username__startswith='L')
不区分大小写
u = User.objects.filter(username__istartswith='L') - endswith
以...结尾 (区分大小写)
u = User.objects.filter(username__endswith='Y')
不区分大小写
u = User.objects.filter(username__iendswith='Y') - null
查询数据为null
# 查询为null的数据
u = User.objects.filter(username__isnull=True)
u = User.objects.filter(username=None)
# 查询不为空的数据
u = User.objects.filter(username__isnull=False)
u = User.objects.exclude(username__isnull=True) - in
是否包含范围内
# 包含范围内
u = User.objects.filter(id__in=[1,2,3,4,5])
u = User.objects.filter(pk__in=[1,2,3,4,5])
# 不包含范围内
u = User.objects.exclude(pk__in=[1,2,3,4,5]) - 比较运算符
- gt 大于
- gte 大于等于
- lt 小于
- lte 小于等于
u = User.objects.filter(id__gt=10)
u = User.objects.filter(id__gte=10)
u = User.objects.filter(id__lt=10)
u = User.objects.filter(id__lte=10)
5、聚合函数
- 导入
from django.db.models import Avg,Max,Min,Sum,Count - 方法
aggregate() - 实例
u = User.objects.aggregate(Avg('age'))
u = User.objects.aggregate(Max('age'))
u = User.objects.aggregate(Min('age'))
u = User.objects.aggregate(Sum('age'))
u = User.objects.aggregate(Count('age'))
6、限制结果数量all()
-
和列表截取一样的操作
u = User.objects.all()
print(u[0])
print(u[100])
print(u[0:10])
print(u[0:10:2])
五、修改与删除
1、修改
- save()
def update(req):
# 获取要修改数据的对象
u1 = User.objects.get(pk=1)
print(u1)
u1.sex = False
u1.age = 17
u1.save()
return HttpResponse('update') - update() 值的修改
# 修改多个
u = User.objects.filter(id__in=[1,2,3])
# print(u)
u.update(age=17, sex=False) - 区别
save适用于修改单个对象
update适用于修改多个对象
2、删除
- delete
u = User.objects.filter(id__in=[1,2,3])
u.delete()
六、高级查询
1、Q对象
- 导入
from django.db.models import Q - 作用
逻辑或
# 逻辑或
u = User.objects.filter(Q(age=18)|Q(sex=True))
# 逻辑与
u = User.objects.filter(age=18, sex=True)
u = User.objects.filter(age=18).filter(sex=True) - 逻辑非
u = User.objects.filter(~Q(age=18))
u = User.objects.exclude(Q(age=18))
2、F对象
- 导入
from django.db.models import F - 概述
模型类中A与B字段之间的比较
# 比较俩个字段相等的值
u = User.objects.filter(id=F('age'))
# 比较id大于age字段的值
u = User.objects.filter(id__gt=F('age'))
3、原生SQL操作
- 格式
类名.objects.raw(sql) - 实例
u = User.objects.raw('select * from user')
u = User.objects.raw('select id, u_age, sex from user') - 注意
查询某个字段时 包含主键
4、获取原生SQL
- 格式
对象.query - 示例
u = User.objects.filter(id__gt=F('age'))
print(u)
print(u.query)
5、关联查询
- 作用
俩个表关联 - 语法
关联模型类名小写__属性名__ 比较运算符=值 - 实例
s = Grade.objects.filter(students__sname__contains='lucky')
七、模型对应关系
1、概述
- 主从表
没有声明关系的表为主表
声明关系的表为从表 - 对应关系
- 一对一
- 一对多
- 多对多
2、一对一模型关系 OneToOneField
-
说明
使用OneToOneField声明模型关系为一对一关系将OneToOneField放在从表中 -
使用场景
表的字段太多 进行拆分 -
关系位置
哪张表都可以 -
创建模型类
用户模型类
from django.db import models# Create your models here. class User(models.Model): # 用户名 username = models.CharField(max_length=12) # 密码 userpass = models.CharField(max_length=64) # 性别 sex = models.BooleanField(default=True) # 年龄 age = models.SmallIntegerField(default=18, db_column='u_age') # 个人简介 info = models.CharField(max_length=200, default='个人简介') # 头像 icon = models.CharField(max_length=60, default='default.jpg') # 是否删除 isDelete = models.BooleanField(default=False) # 注册时间 registerTime = models.DateTimeField(auto_now_add=True) # 类方法用于添加数据 def __str__(self): return self.username class Meta: db_table = 'user' # 更改表名称为user
身份证模型类
# 身份证
class IdCard(models.Model):
# 身份证号码
num = models.CharField(max_length=18)
name = models.CharField(max_length=10)
sex = models.BooleanField(default=True)
birth = models.DateTimeField(auto_now_add=True)
address = models.CharField(max_length=50, default='地址')
# 创建了模型一对第一的关系 从表随着主表的删除而删除
# user = models.OneToOneField(User, on_delete=models.CASCADE)
# 受保护 模式 如果从表有关联数据 则不能删除主表关联的数据
# user = models.OneToOneField(User, on_delete=models.PROTECT)
# 置空模式 设置为null
user = models.OneToOneField(User, on_delete=models.SET_NULL, null=True)
def str(self):
return self.name
class Meta:
db_table = 'idcard' # 更改表名称为user -
添加一对一模型数据
添加主表
def addUser(req):
User(username='张三').save()
User(username='李四').save()
User(username='王五').save()
return HttpResponse('一对一模型关系添加User数据')
添加从表
def addIdCard(req):
import random
u = User.objects.first()
IdCard(num=random.randrange(100000000,99999999999), name=u.username,user=u).save()
return HttpResponse('一对一模型关系添加IdCard数据') -
查询
通过主表查从表
主表对象.从表类名小写
u = User.objects.first()
# print(u)
print(u.idcard)
print(u.idcard.num)
通过从表查主表
从表对象.外键属性名
idcard = IdCard.objects.first()
# print(idcard)
print(idcard.user)
print(idcard.user.sex) -
删除
def delUser(req):
u = User.objects.first()
u.delete()
return HttpResponse('删除主表')def delIdCard(req): idcard = IdCard.objects.first() idcard.delete() return HttpResponse('删除从表')
3、一对多模型关系
-
说明
使用ForeignKey创建模型一对多关系 -
位置
放在多的一方 -
创建模型
Grade班级
from django.db import models# 创建班级模型 class Grade(models.Model): gname = models.CharField(max_length=10, default='python36') gnum = models.SmallIntegerField(default=30) gboynum = models.SmallIntegerField(default=15) ggirlnum = models.SmallIntegerField(default=15) def __str__(self): return self.gname class Meta: db_table = 'grade'
student模型类
# 创建学生模型
class Student(models.Model):
sname = models.CharField(max_length=10, default='张三')
sage = models.SmallIntegerField(default=18)
ssex = models.BooleanField(default=True)
# 一对多外键关系 从表随着主表而删除
# sgrade = models.ForeignKey(Grade, on_delete=models.CASCADE)
# sgrade = models.ForeignKey(Grade, on_delete=models.SET_NULL, null=True)
# sgrade = models.ForeignKey(Grade, on_delete=models.PROTECT)
sgrade = models.ForeignKey(Grade, on_delete=models.SET_DEFAULT, default=1)def __str__(self): return self.sname class Meta: db_table = 'student'
-
路由
path(r'addgrade/', onetomany.addGrade),
path(r'addstudent/', onetomany.addStudent), -
添加数据
添加主表grade数据
# 添加班级数据
def addGrade(req):
Grade(gname='python36').save()
Grade(gname='python37').save()
Grade(gname='python38').save()
return HttpResponse('添加班级数据')
添加从表student数据
def addStudent(req):
g36 = Grade.objects.first()
Student(sname='张三', sgrade=g36).save()
Student(sname='李四', sgrade=g36).save()
Student(sname='王五', sgrade=g36).save()
Student(sname='赵六', sgrade=g36).save()
return HttpResponse('添加学生数据') -
查询
主查从(班级查学生)
# 查询
def showStudent(req):
# 通过班级查学生
g36 = Grade.objects.first()
s = g36.student_set.all()
print(s)
return HttpResponse('主查从')
从查主(学生查班级)
def showGrade(req):
s = Student.objects.first()
g = s.sgrade.gname
print(g)
return HttpResponse('从查主') -
删除
主表数据删除(从表会跟随着on_delete而变化)
# 删除数据
def delGrade(req):
g = Grade.objects.first()
g.delete()
return HttpResponse('删除主表数据')
从表数据删除
def delStudent(req):
s = Student.objects.first()
s.delete()
return HttpResponse('删除从表数据')
4、多对多
-
说明
使用ManyToManyField创建多对多模型关系 -
原理
底层是由俩个外键实现的 会生成中间表 进行存储id -
关系
放在哪张表都可以 -
创建模型类
User模型类
class User(models.Model):
# 用户名
username = models.CharField(max_length=12)
# 密码
userpass = models.CharField(max_length=64, default='123456')
# 性别
sex = models.BooleanField(default=True)
# 年龄
age = models.SmallIntegerField(default=18, db_column='u_age')
# 个人简介
info = models.CharField(max_length=200, default='个人简介')
# 头像
icon = models.CharField(max_length=60, default='default.jpg')
# 是否删除
isDelete = models.BooleanField(default=False)
# 注册时间
registerTime = models.DateTimeField(auto_now_add=True)# 类方法用于添加数据 def __str__(self): return self.username class Meta: db_table = 'user' # 更改表名称为user
博客模型
class Posts(models.Model):
title = models.CharField(max_length=20, default='标题')
article = models.CharField(max_length=200, default='博客内容')
createTime = models.DateTimeField(auto_now_add=True)
# 外键 多对多
users = models.ManyToManyField(User)
def str(self):
return self.title
class Meta:
db_table = 'posts' -
添加数据
添加用户数据User
def addUser(req):
User(username='张三').save()
User(username='李四').save()
User(username='王五').save()
return HttpResponse('一对一模型关系添加User数据')
添加博客数据Posts
# 添加博客数据
def addPosts(req):
Posts(title='以后的你终将感谢拼搏的自己').save()
Posts(title='大朗与金莲').save()
Posts(title='红楼梦').save()
return HttpResponse('添加博客数据') -
收藏功能(将数据添加到中间表中)
添加单个收藏
u1 = User.objects.first()
p1 = Posts.objects.first()
p1.users.add(u1)
添加多个收藏
u1 = User.objects.first()
u2 = User.objects.last()
p1 = Posts.objects.last()
p1.users.add(u1, u2) -
多对多数据查询
用户收藏哪些博客
# 多对多查询
def showPosts(req):
u1 = User.objects.first()
p = u1.posts_set.all()
print(p)
return HttpResponse('查看用户收藏了哪些博客')
博客被谁收藏了
def showUsers(req):
# 博客被谁收藏了
p1 = Posts.objects.first()
u = p1.users.all()
print(u)
return HttpResponse('查看博客都被谁收藏了') -
取消收藏
删除单条数据
def delColl(req):
u1 = User.objects.first()
p1 = Posts.objects.first()
p1.users.remove(u1)
return HttpResponse('删除收藏')
删除多条数据
u4 = User.objects.get(pk=4)
u5 = User.objects.get(pk=5)
p1 = Posts.objects.first()
p1.users.remove(u4,u5)
八、模型类继承
1、普通继承
from django.db import models
class A(models.Model):
name = models.CharField(max_length=10, default='name')
age = models.SmallIntegerField(default=18)
class B(A):
class Meta:
db_table = 'b'
class C(A):
class Meta:
db_table = 'c'
如果此刻进行迁移:则A类也会创建出模型
2、将父类进行抽象化
from django.db import models
class A(models.Model):
name = models.CharField(max_length=10, default='name')
age = models.SmallIntegerField(default=18)
class Meta:
# 抽象类
abstract = True
class B(A):
class Meta:
db_table = 'b'
class C(A):
class Meta:
db_table = 'c'
将父类抽象化以后 不会进行创建
本文来自博客园,作者:寻月隐君,转载请注明原文链接:https://www.cnblogs.com/QiaoPengjun/articles/15948811.html