Django篇(二)
- 2019 年 10 月 6 日
- 笔记
配置使用mysql数据库
之前我们使用的是Django中自带的数据库sqlite数据库。
这篇文章让我们切换成mysql,不会MySQL基础的可以去查询数据库篇的文章。
1、创建项目
2、创建应用
3、注册应用
4、修改setting.py来让我们的Django框架支持mysql数据库。
在setting.py找到DATABASES,修改成:
DATABASES = {
'default': {
'ENGINE':'django.db.backends.mysql',
'NAME':'student',
'USER':'root',
'PASSWORD':'123456',
'HOST':'localhost',
'PORT':3306,
}
}
ENGINE:选择数据库
NAME:数据库的名字
USER:登陆账号
PASSWORD:密码
HOST:本地填写localhost,不是就写ip地址
PORT:3306.
5、我们还需要安装操作mysql的模块
在虚拟环境中pip instal pymysql
6、在test3下的test3下的__init__添加:
import pymysql
pymysql.install_as_MySQLdb()
此时我们运行项目就不会有问题了。
常见模型字段属性
模型属性命名:
1、不能是python保留关键字
2、不允许出现联系的下划线
字段类型
第一篇文章中我们仅仅了解了几个。
接下来我们重新了解一下有什么其他模型。
首先在使用时,我们需要导入django.db.models包
AutoField:
自动增长的IntegerField,通常不需要我们写,一般会自动生成。不指定时,Django会自动生成字段为id的自增长字段。
BooleanField:
布尔字段,为True或者False
NullBooleanField:
允许为Null,True,False
CharField(max_length=最大长度):
字符串类型,max_length表示支持的最大字符串,是必须给的参数。
TextField:
大文本字段,一般超过4000个字,才会使用它。
IntegerField:
整数字段
DecimalField():
浮点数,参数max_digits表示允许的最多位数,
decimal_places表示小数的位数
FloatField;
浮点数,参数和上面的一样,但是没有上面的精确。
DateField:
日期(年月日),参数autu_now=True,表示每次保存的,自动的添加现在的时间
参数auto_now_add=True,表示添加时候的时间,
这两个属性是互斥的,只能存在一个。
TimeField:
时间(时分秒):参数和上面的一样。
DateTimeField:
时间(年月日,时分秒),参数同上。
FileField:
上传文件字段。
ImageField:
继承FileField,对上传的照片进行校验,保证是有效的照片。
公用属性
default:默认值
primary_key:若为True,则是主键,一般搭配AutoField使用。
unique:唯一值
db_index:若为True,则会为此字段创建索引。
db_column:指定字段名字,未指定会使用属性名称。
null:若为True,表示该字段允许为空。
blank:这个属性与后台admin有关,是否允许在后台添加值的时候是否为空。
注意:我们在添加属性的时候如果影响了表结构,就需要迁移,default和blank不影响表结构。
更多模型字段,请参考Django官方文档。写的明明白白。
查询
我们在Django中通过操作模型类去做增删改查,sql语句那么多,我们同样可以进行增删改查。
其中最复杂的也就是查询了。下面我们来看一下。
查询函数
我们在Django中通过:模型类.objects属性调用以下函数来进行查询
get:
返回表中满足条件的一条数据,有且只能有一条,查询出多条会报异常。
查询不到数据也会报异常。
all:
返回全部数据,返回的类型是QuerySet。
filter:
返回符合条件的,和get不同,这个可以返回多条数据。返回的类型是QuerySet。
exclude:
返回不满足此条件的,也是可以返回多条数据,返回类型也是QuerySet。
order_by:
对查询的结果进行排序,返回类型也是QuerySet。
以下我们以模型类为stuinfo是实例。
get实例:
查询id为1的数据:
stuinfo.objects.get(id = 1)
all实例:
查询所有数据:
stuinfo.objects.all()
filter实例:
条件格式:字段名__条件名 = 值
1、等于条件名为exact
查询年龄(age)为18的人
student.objects.filter(age__exact = 18)
2、模糊查询条件名为contains
2.1查询名字(name)中含有张的人
student.objects.filter(name__contains='张')
2.2查询以名字三结尾的人
student.objects.filter(name__endswith='三')
2.3查询以李开头的人
student.objects.filter(name__startswith='李')
3、空查询 isnull
3.1查询备注(context)为空的人
student.objects.filter(context__isnull=True)
3.2查询备注(context)不为空的人
student.objects.filter(context__isnull=False)
4、范围查询 in
查询id等于1和2的人
student.objects.filter(id__in=[1,2])
5、比较查询 gt(大于) lt(小于) gte(大于等于) lte(小于等于)
5.1查询id大于3的人
student.objects.filter(id__gt=3)
5.2查询id大于等于3的人
student.objects.filter(id__gte=3)
5.3查询id小于3的人
student.objects.filter(id__lt=3)
5.4查询id小于等于3的人
student.objects.filter(id__lte=3)
6、日期查询
6.1查询生日(bir_date)是1998年出生的人
student.objects.filter(bir_date__year=1998)
6.2查询生日(bir_date)是5月出生的人
student.objects.filter(bir_date__month=5)
6.3查询生日(bir_date)是1998,1,1以后出生的
from datetime import date
student.objects.filter(bir_date__gt=date(1998,1,1))
exclude实例
查询id不等以1的人
student.objects.exclude(id = 1)
order_by实例
查询所有人按照ids从小到大排序
student.objects.all().order_by('id')
查询所有时,可以省略all()
student.objects.order_by('id')
查询所有人按照ids从大到小排序
student.objects.all().order_by('-id')
也可以根据多个字段排序
根据id和age进行排序
student.objects.all().order_by('id','age')
注意:以上只要返回值为QuerySet类型,都可以再次进行以上任何操作。
Q对象
以上我们都是单个条件进行查询,那如果多个条件呢?
我们可以在上面获取的对象再次进行筛选,也就是注意中说的那句话,但是很麻烦。
因此Django为我们提供了Q模块来帮助我们多条件查询。
首先我们需要导入Q模块:
from django.db.models import Q
Q实例:
在实例之前,在Filter中是可以进行and操作的,但是不能进行or操作。
比如查询id大于3,年龄(age)大于18的人:
student.objects.filter(id__gt=3,age__gt=18)
用Q对象查询 and用Q对象中的&符号:
student.objects.filter(Q(id__gt=3)&Q(age__gt=18))
|对应or
查询id=1或者age大于25的人:
student.objects.filter(Q(id=1)|Q(age__gt=25))
Q对象中还能进行非操作~:
查询id不等于2的人
student.objects.filter(~Q(id=2))
F对象
多条件可以解决,那属性之间的比较怎么解决?
F对象
导入F对象:
from django.db.models import F
查询id大于年龄(age)的人
student.objects.filter(id__gt=F('age'))
聚合函数
在mysql中有sum,count,avg,max,mix等聚合函数,
我们操作模型同样可以达到效果:
导入聚合类模块
from django.db.models import Sum,Avg,Count,Max,Mix
聚合函数实例
使用聚合函数需要使用aggregate来操作
查询所有人的数目
student.objects.all().aggregate(Count('id'))
查询年龄(age)的和
student.objects.all().aggregate(Sum('age'))
其他就不一一实例了。
上面返回的是一个字典:
比如查询的所有人的数目返回:
{'id__count':值}
年龄和:
{'age__sum':值}
key值是字典加双下划线加聚合函数的名字。
count函数
查询所有人的数目也可以这样写
student.objects.all().count()
注意:当返回值类型为QuerySet类型时,我们称他为一个查询集,可以再次进行以上任何操作。
查询集的特性
1、惰性查询
只有当我们使用数据的时候,才会在mysql中去查询。
2、缓存
当我们使用同一个查询集的时候,只有第一次是执行到数据库,然后把结果储存起来,当我们再次使用这个查询集的时候,就会调用我们缓存中的数据。
查询集相当于一个列表,我们取值可以遍历取出,也可以进行下表或者切片取出。
当我们对一个查询集进行切片或下标查询,会返回一个新的查询集。
不同的是我们的切片不允许为负值。
判断一个查询集是否有数据。
查询集.exists(),有返回True,没有返回False
模型类关系
1、一对多关系
例如一个班级对应多个人
我们需要用ForeignKey()来关联我们的模型。
2、多对多
一个老师对应多个学生,一个学生对应多个老师
那么老师表和学生表就是多对多的关系。
我们需要使用ManyToManyField(),那么你会说我定义在那个表里了?定义那个表都行。
3、一对一关系
学生的学号和学生的详细信息表就是一对一的关系。
可以用OneToOneField来定义,定义那个一个类都可以。
关联查询(一对多)
关联实例班级表(classinfo),学生表(stuinfo)
查询班级id为1的所有学生:
# 查询到id为1的班级
c = classinfo.objects.get(id=1)
# 利用关联的表加__set来查询
c.stuinfo__set.all()
反过来,查询id为1的学生的班级名称
# 查询id=1的学生
s = student.objects.get(id=1)
# 直接通过关联的字段来查询
s.关联字段,比如s.c_id
以上很麻烦,我们直接通过模型类来查询
实例:
查询班级表中学生的名字包含张的班级
classinfo.objects.filter(stuinfo__name__contains = '张')
你想要得到那张表,就用那张表去查询。
查询学生表中,班级表中id为1的学生.
# 学生表中有关联的字段,我们通过关联的字段来查询。
stuinfo.objects.filter(c_id__id = 1)
自关联
自关联是一种特殊的一对多的关系,
我们在关键模型类的时候,需要使用ForgignKey('self'),表示关联自己。
同样的查询方式。
管理器
什么是管理器?
我们每次查询的时候都会是模型.objects.xxx。
这个objects是Django帮我们自动生成的管理器对象。通过objects来帮助我们查询信息。
objects是models.Manger的一个对象,也就是说objects继承于models.Manger。
同样我们可以不使用Django帮我们生成的,我们可以自己创建一个。
为什么要自己创建?
1、过滤查询集,比如你查询全部数据,我只让你返回前十条。
2、添加新的方法,比如添加,修改可以封装在里面方面我们使用。
过滤查询集实例
如果我们在models.py中创建一个模型:
# 创建stuinfo表
class stuinfo(model.Model):
# name 字符串类型 最大长度为20
name = mdoels.CharField(max_length=20)
# age 数字类型
age = model.IntegerField()
# 自定义一个管理器对象
# objects是我定义的一个名字,你可以定义成其他的
# stuinfoManage是我定义的管理器的类名,同样你可以定义成其他
objects = stuinfoManage()
# 定义管理类,继承model.Manager
class stuinfoManage(model.Manager):
# 该更返回的查询集
# 重新定义all方法
def all(self):
# 调用父类方法中的all()查询到全部内容
s = super().all()
# 过滤数据,只显示id小于10的数据
s = s.filter(id__lt=10)
# 返回数据
return s
添加新的方法实例
同样我们在上面的stuinfoManage中添加一个新方法添加
class stuinfoManage(model.Manager):
# 该更返回的查询集
# 重新定义all方法
def all(self):
# 调用父类方法中的all()查询到全部内容
s = super().all()
# 过滤数据,只显示id小于10的数据
s = s.filter(id__lt=10)
# 返回数据
return s
# 添加一个添加方法
def stu_create(self,name,age):
# 实例化stuinfo类
# 这里我们给大家介绍一个新的方法
# stuinfo.objects.model 返回的就是stuinfo
# 所以我们这个实例对象不需要s = stuinfo()了
s = self.model
s = s()
s.name = name
s.age = age
s.save()
return s
你能想到为我们的添加方法封装,那Djang的创造者自然也想得到。
我们添加的时候需要:
不过这里需要指定参数传递
student.objects.cretae(name='张三',age=18)
元选项
以上我们都是先创建好模型再去迁移,创建表,
试想,如果我们的数据库已经存在呢?
比如我们在数据库创建的表是stu,
我们的模型是stuinfo,我们可以给他指定一个数据库里的表
class stuinfo(model.Model):
name = mdoels.CharField(max_length=20)
age = model.IntegerField()
# 我们需要在模型里再定义一个Meta类
class Meta:
db_table = 'stu'
即可。
orm映射的表名也即是我们在自动生成表的表名是:
应用名_类名。
所以你去修改数据的表名也是可以实现的。
另:前端知识希望自己补充.