数据库
1.定义模型类
在models.py中定义模型类,继承自models.Model
from django.db import models
# Create your models here.
class 模型类A(models.Model):
# 创建字段,字段类型...
name = models.CharField(max_length=10)
class 模型类B(models.Model):
gender = models.BooleanField()
# 外键约束(B中某物属于A中某类)
book = models.ForeignKey(模型类A,on_delete=models.CASCADE)
模型类优化
class 模型类A(models.Model):
name = models.CharField(max_length=10)
# ------------------------------------------
def __str__(self):
"""将模型类以字符串的方式输出"""
return self.name
1)主键
django会为表创建自动增长的主键列,每个模型只能有一个主键列,如果选项设置某属性为主键列后,django将不会再创建自动增长的主键列。
默认创建的主键列属性为id,可以使用pk代替(全屏为primary key)
2)属性命名限制
不能是python的保留关键字
不允许使用连续下划线(django查询方式决定)
定义属性时需要指定字段类型,语法:属性=models.字段类型(选项)
字段类型
类型 说明
AutoField 自动增长的IntegerField,通常不用指定,不指定时Django会自动创建属性名为id的自动增长属性
BooleanField 布尔字段,值为True或False
NullBooleanField 支持Null、True、False三种值
CharField 字符串,参数max_length表示最大字符个数
TextField 大文本字段,一般超过4000个字符时使用
IntegerField 整数
DecimalField 十进制浮点数, 参数max_digits表示总位数, 参数decimal_places表示小数位数
FloatField 浮点数
DateField 日期, 参数auto_now表示每次保存对象时,自动设置该字段为当前时间,用于"最后一次修改"的时间戳,它总是使用当前日期,默认为False; 参数auto_now_add表示当对象第一次被创建时自动设置当前时间,用于创建的时间戳,它总是使用当前日期,默认为False; 参数auto_now_add和auto_now是相互排斥的,组合将会发生错误
TimeField 时间,参数同DateField
DateTimeField 日期时间,参数同DateField
FileField 上传文件字段
ImageField 继承于FileField,对上传的内容进行校验,确保是有效的图片
选项
选项 说明
null 如果为True,表示允许为空,默认值是False
blank 如果为True,则该字段允许为空白,默认值是False
db_column 字段的名称,如果未指定,则使用属性的名称
db_index 若值为True, 则在表中会为此字段创建索引,默认值是False
default 默认
primary_key 若为True,则该字段会成为模型的主键字段,默认值是False,一般作为AutoField的选项使用
unique 如果为True, 这个字段在表中必须有唯一值,默认值是False
外键
在设置外键时,需要通过on_delete选项指明主表删除数据时,对于外键引用表数据如何处理,在django.db.models中包含了可选常量:
- CASCADE级联,删除主表数据时连通一起删除外键表中数据
- PROTECT保护,通过抛出ProtectedError异常,来阻止删除主表中被外键应用的数据
- SET_NULL设置为NULL,仅在该字段null=True允许为null时可用
- SET_DEFAULT设置为默认值,仅在该字段设置了默认值时可用
- SET()设置为特定值或者调用特定方法
- DO_NOTHING不做任何操作,如果数据库前置指明级联性,此选项会抛出IntegrityError异常
2.配置数据库
setting.py中默认使用sqlite数据库
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
使用mysql数据库
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'HOST': '127.0.0.1', # 数据库主机
'PORT': 3306, # 数据库端口
'USER': 'root', # 数据库用户名
'PASSWORD': 'mysql', # 数据库用户密码
'NAME': 'book' # 数据库名字
}
}
3.模型迁移
生成迁移文件:根据模型类生成创建表的语句
python manage.py makemigrations
执行迁移:根据第一步生成的语句在数据库中创建表
python manage.py migrate
4.运行测试
需要安装MySQL数据库的客户端驱动
pip install mysqlclient==1.4.6 -i https://pypi.tuna.tsinghua.edu.cn/simple/
若还是报错,则需要安装libmysqlclient-dev(虚拟机中)
sudo apt-get install libmysqlclient-dev
5.数据库操作
增
1)save
>>> from 子应用名.models import 类名
>>> 对象a = 模型类A(
... name='python入门',
... pub_date='2010-1-1'
... )
>>> 对象a.属性1 = 属性值
>>> 对象a.属性2 = 属性值
>>> 对象a.save()
2)create
>>> 模型类A.objects.create(
... name='itheima',
... book=book
... )
改
1)save
修改模型类对象的属性,然后执行save()
>>> 对象a = 模型类A.objects.get(属性='原信息')
>>> 对象a.属性 = '新信息'
>>> 对象a.save()
2)update
>>> 模型类A.objects.filter(属性='原信息').update(属性='新信息')
删
1)模型类对象delete
>>> 对象a = 模型类A.objects.get(属性='信息')
>>> 对象a.delete()
2)模型类.objects.filter().delete()
>>> 模型类A.objects.filter(属性='信息').delete()
查
基本查询
1)get 查询单一结果,如果不存在会抛出模型类.DoesNotExist异常
>>> 模型类A.objects.get(属性=信息)
2)all 查询多个结果
>>> 模型类A.objects.all()
3)count 查询数量
>>> 模型类A.objects.count()
4)filter 查询所有
>>> 模型类A.objects.filter()
5)exclude() 不等于 取反
>>> 模型类A.objects.exclude()
过滤查询
属性名称__比较运算符=值
# 属性名称和比较运算符间使用两个下划线,所以属性名不能包括多个下划线
BookInfo.objects.filter(id__exact=1)
可简写为:
BookInfo.objects.filter(id=1)
比较运算符 功能 举例
exact 相等 可简写为:id=1
contains 是否包含 __contains='传'
startswith、endswith 指定开头或结尾 __endswith='部'
isnull 是否为空 __isnull=True
in 是否在范围内 __in=[1,3,5]
gt,gte,lt,lte 大于,大于等于,小于,小于等于 __gt=3
year,month,day,week_day,hour,minute,second 日期时间类型 __year=1980
例:查询1990年1月1日后发表的图书。
>>> BookInfo.objects.filter(pub_date__gt='1990-1-1')
F 实现属性之间的比较
from django.db.models import F,Q
# 阅读量大于等于2倍评论量
BookInfo.objects.filter(breade__gte = F('bcomment'))
Q 实现mysql里的not and or
符号 功能
& and
| or
~ not
聚合函数.aggregate()
返回一个字典
Avg 平均
Count 数量 一般不使用,直接用count()
Max 最大 aggregate(Max(‘属性’))
Min 最小
Sum 求和
排序 .order_by()
升序: .order_by(‘属性’)
降序: .order_by(’-属性rd’)
关联查询
获取1对应的多的一方的数据
# 1的对象.多的模型类小写_set.all()
bookinfo.heroinfo_set.all()
获取多对应的1的一方的数据
# 直接使用外键
heroinfo.bookinfo
heroinfo.bookinfo_id
关联过滤查询
查询英雄是郭靖的书籍
bookinfo.object.filter(heroinfo__name='郭靖')
查询图书 书的描述包含’掌’
bookinfo.objects.filter(heroinfo__desc__contains='掌')
查询多的模型 条件是对1的一方属性进行判断
条件使用关联的模型类的字典 1模型类外键名__1模型类属性名__条件运算符=值
查询天龙八部的所有英雄
heroinfo.objects.filter(book_title='天龙八部')
查看MySQL日志的位置
cat mysql.log
查询集QuerySet
1.惰性执行
创建查询集不会访问数据库,直到调用时才会访问数据库,调用情况包括迭代、序列化、与if合用。
books = bookinfo.objects.all() # 这时查看MySQL日志发现没有执行
for b in books:
print(b.title) # 执行了语句
2.缓存
使用一个查询集,第一次使用时会发生数据库的查询,然后django会把结果缓存下来,再次使用这个查询集时会使用缓存的数据,减少了数据库的查询次数。
情况1:每次查询都与数据库进行交互,增加了数据库的负载
for i in hero.object.all():
print(i.name)
for i in hero.object.all():
print(i.name)
情况2:经过存贮后,可以重用查询集,第二次使用缓存中的数据
heros = heroinfo.object.all()
for i in heros:
print(i.name)
for i in heros:
print(i.name)