配置
在settings.py中保存了数据库的连接配置信息,Django默认初始配置使用sqlite数据库。
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
- 使用MySQL数据库首先需要安装驱动程
pip install PyMySQL
- 在Django的工程同名子目录的init.py文件中添加如下语句
import pymysql
pymysql.install_as_MySQLdb()
作用是让Django的ORM能以mysqldb的方式来调用PyMySQL。
3.修改DATABASES配置信息
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'HOST': '127.0.0.1', # 数据库主机
'PORT': 3306, # 数据库端口
'USER': 'root', # 数据库用户名
'PASSWORD': 'mysql', # 数据库用户密码
'NAME': 'book' # 数据库名字
}
}
- 在MySQL中创建数据库
create database book charset=utf8;
定义模型类
1.定义模型类中的字段分成三部分
* 字段名
* 字段名不能使用python关键字或者mysql关键字
* 字段名不能出现连续的 下划线
字段类型
- 基本和数据库中的类型一致
常见的字段类型:
类型 说明 AutoField 自动增长的IntegerField,通常不用指定,不指定时Django会自动创建属性名为id的自动增长属性 BooleanField 布尔字段,值为True或False AutoField 支持Null、True、False三种值 CharField 字符串,参数max_length表示最大字符个数 IntegerField 整数 FloatField 浮点数 DateField 日期
字段选项
常见字段选项
选项 说明 如果为True,表示允许为空,默认值是False blank 如果为True,则该字段允许为空白,默认值是False db_column 字段的名称,如果未指定,则使用属性的名称 db_index 若值为True, 则在表中会为此字段创建索引,默认值是False default 默认 primary_key 若为True,则该字段会成为模型的主键字段,默认值是False,一般作为AutoField的选项使用 unique 如果为True, 这个字段在表中必须有唯一值,默认值是False 外键级联操作
- on_delete 级联操作有常见有三种可选
- 同步删除
- 拒绝删除
- set null
- on_delete 级联操作有常见有三种可选
示例代码:
from django.db import models
# Create your models here.
# Create your models here.
# 准备书籍列表信息的模型类
class BookInfo(models.Model):
# 创建字段,字段类型...
name = models.CharField(max_length=20, verbose_name='名称')
pub_date = models.DateField(verbose_name='发布日期',null=True)
readcount = models.IntegerField(default=0, verbose_name='阅读量')
commentcount = models.IntegerField(default=0, verbose_name='评论量')
is_delete = models.BooleanField(default=False, verbose_name='逻辑删除')
class Meta:
db_table = 'bookinfo' # 指明数据库表名
verbose_name = '图书' # 在admin站点中显示的名称
def __str__(self):
"""定义每个数据对象的显示信息"""
return self.name
# 准备人物列表信息的模型类
class PersonInfo(models.Model):
GENDER_CHOICES = (
(0, 'male'),
(1, 'female')
)
name = models.CharField(max_length=20, verbose_name='名称')
gender = models.SmallIntegerField(choices=GENDER_CHOICES, default=0, verbose_name='性别')
description = models.CharField(max_length=200, null=True, verbose_name='描述信息')
# 外键
# on_delete 级联操作 同步删除,拒绝删除,set null
# models.CASCADE CASCADE同步操作
book = models.ForeignKey(BookInfo, on_delete=models.CASCADE, verbose_name='图书') # 外键
is_delete = models.BooleanField(default=False, verbose_name='逻辑删除')
class Meta:
db_table = 'peopleinfo'
verbose_name = '人物信息'
def __str__(self):
return self.name
数据库操作
增加数据
方式1: save()
这种方式 数据不会自动入库
>>> book = BookInfo()
>>> book.name = '老陈回忆录'
>>> book.pub_date = '2018-11-11'
>>>
想让数据入库 需要手动调用 save() 方法
>>> book.save()
方式1: create()
这种方式数据直接入库
>>> BookInfo.objects.create(name='那年老陈19岁',pub_date='2018-11-12')
<BookInfo: 那年老陈19岁>
修改
方式1: save()
修改模型的属性,手动调用 save方法 数据才会修改
>>> book = BookInfo.objects.get(id=7)
>>> book.pub_date = '2016-11-11'
<!--需要手动执行save() 数据才会修改-->
>>> book.save()
方式2: update()
模型类执行update方法,数据直接修改,会返回受影响的行数
>>> BookInfo.objects.filter(id=8).update(readcount=100)
1
>>>
删除
方式1: 通过模型类删除
>>> book = BookInfo.objects.get(pk=8)
>>> book
<BookInfo: 那年老陈19岁>
>>> book.delete()
(1, {'book.BookInfo': 1, 'book.PersonInfo': 0})
>>>
方式2: 直接删
模型类.objects.get().delete()
>>> book = BookInfo.objects.get(id=7).delete()
>>> book
(1, {'book.BookInfo': 1, 'book.PersonInfo': 0})
>>>
==查询==
基本查询
- get 是获取一条记录
>>> BookInfo.objects.get(id=1)
<BookInfo: 射雕英雄传>
- get 获取不到是会报异常 ==DoesNotExist==
>>> BookInfo.objects.get(id=11111)
book.models.DoesNotExist: BookInfo matching query does not exist.
- all 获取所有数据
>>> BookInfo.objects.all()
<QuerySet [<BookInfo: 射雕英雄传>, <BookInfo: 天龙八部>, <BookInfo: 笑傲江湖>, <BookInfo: 雪山飞狐>]>
- count 获取查询结果的个数
>>> BookInfo.objects.all().count()
4
>>>
过滤查询
- get过滤单一结果
- filter过滤出多个结果
exclude排除掉符合条件剩下的结果
- get
通过字段过滤一条结果
>>> BookInfo.objects.get(id=1)
<BookInfo: 射雕英雄传>
- 使用属性名称__比较运算符=值 方式获取
>>> BookInfo.objects.get(id__exact=1)
<BookInfo: 射雕英雄传>
- 通过主键的方式获取
>>> BookInfo.objects.get(pk=1)
<BookInfo: 射雕英雄传>
- 使用filter过滤出结果集
>>> BookInfo.objects.filter(id=1)
<QuerySet [<BookInfo: 射雕英雄传>]>
>>>
filter 和 get 区别 ,filter得到的是一个查询结果集,get得到的是一个对象
filter 过滤出多个结果 (0,1,多个 都包括 多个结果中)
- contains 包含
>>> BookInfo.objects.filter(name__contains='八')
<QuerySet [<BookInfo: 天龙八部>]>
- startswith、endswith:以指定值开头或结尾。
>>> BookInfo.objects.filter(name__endswith='湖')
<QuerySet [<BookInfo: 笑傲江湖>]>
- isnull:是否为null。
>>> BookInfo.objects.filter(name__isnull=False)
<QuerySet [<BookInfo: 射雕英雄传>, <BookInfo: 天龙八部>, <BookInfo: 笑傲江湖>, <BookInfo: 雪山飞狐>]>
- in:是否包含在范围内。
>>> BookInfo.objects.filter(id__in=[1,2,3])
<QuerySet [<BookInfo: 射雕英雄传>, <BookInfo: 天龙八部>, <BookInfo: 笑傲江湖>]>
- 比较查询
- gt 大于
- gte 大于等于
- lt 小于
- lte 小于等于
>>> BookInfo.objects.filter(id__gt=2)
<QuerySet [<BookInfo: 笑傲江湖>, <BookInfo: 雪山飞狐>]>
>>> BookInfo.objects.filter(id__gte=2)
<QuerySet [<BookInfo: 天龙八部>, <BookInfo: 笑傲江湖>, <BookInfo: 雪山飞狐>]>
>>>
- 不等于 exclude排除掉符合条件剩下的结果 相当于 not
>>> BookInfo.objects.exclude(id=2)
<QuerySet [<BookInfo: 射雕英雄传>, <BookInfo: 笑傲江湖>, <BookInfo: 雪山飞狐>]>
>>>
- 日期查询
year、month、day、week_day、hour、minute、second:对日期时间类型的属性进行运算。
>>> BookInfo.objects.filter(pub_date__year=1980)
<QuerySet [<BookInfo: 射雕英雄传>]>
>>> BookInfo.objects.filter(pub_date__gt='1990-1-1')
<QuerySet [<BookInfo: 笑傲江湖>]>
>>>
F 和 Q 对象
F对象
对同一个对象中的两个不用的属性之间做比较使用F对象
>>> BookInfo.objects.filter(commentcount__gt=F('readcount'))
<QuerySet [<BookInfo: 射雕英雄传>, <BookInfo: 天龙八部>, <BookInfo: 笑傲江湖>]>
>>>
Q对象
Q对象的对象相当于sql中的 or
>>> from django.db.models import Q
>>> BookInfo.objects.filter(Q(id=1)|Q(commentcount__gt=20))
<QuerySet [<BookInfo: 射雕英雄传>, <BookInfo: 天龙八部>, <BookInfo: 笑傲江湖>, <BookInfo: 雪山飞狐>]>
>>>
Q对象前可以使用~操作符,表示非not。
>>> BookInfo.objects.filter(~Q(id=3))
<QuerySet [<BookInfo: 射雕英雄传>, <BookInfo: 天龙八部>, <BookInfo: 雪山飞狐>]>
>>>
聚合查询
- Max,Min,Sum,Count,Avg
- 聚合函数需要和 aggregate配合使用
- 模型.objects.aggregate(Xxx(‘字段’))
使用aggregate里面加上聚合函数
>>> BookInfo.objects.aggregate(Sum('readcount'))
{'readcount__sum': 126}
>>>
排序
使用order_by对结果进行排序
# 默认升序
>>> BookInfo.objects.all().order_by('readcount')
<QuerySet [<BookInfo: 射雕英雄传>, <BookInfo: 笑傲江湖>, <BookInfo: 天龙八部>, <BookInfo: 雪山飞狐>]>
# 降序 在排序字段前加 -
>>> BookInfo.objects.all().order_by('-readcount')
<QuerySet [<BookInfo: 雪山飞狐>, <BookInfo: 天龙八部>, <BookInfo: 笑傲江湖>, <BookInfo: 射雕英雄传>]>
关联查询
一对多 查询
在一的那方没有多的信息,所以需要反向查询
格式:关联模型类名小写_set.all() 获取关联的所有数据
>>> book = BookInfo.objects.get(pk=1)
>>> book.personinfo_set.all()
<QuerySet [<PersonInfo: 郭靖>, <PersonInfo: 黄蓉>, <PersonInfo: 黄药师>, <PersonInfo: 欧阳锋>, <PersonInfo: 梅超风>]>
>>>
多对一 查询
在多的这方有外键属性,所以我们可以直接使用外键属性,查询到一的那方信息
>>> person = PersonInfo.objects.get(pk=1)
>>> person.book
<BookInfo: 射雕英雄传>
>>>
关联过滤查询
一对多 过滤查询
一的那方没有多的属性,所以需要使用反向查询,我们的写的格式如下:
关联模型类名小写属性名条件运算符=值
>>> BookInfo.objects.filter(personinfo__id = 1)
<QuerySet [<BookInfo: 射雕英雄传>]>
>>>
多对一 过滤查询
多的那方有一的那方属性,所以我们可以通过外键属性获取到一的那方属性,格式如下:
一模型类关联属性名一模型类属性名条件运算符=值
>>> PersonInfo.objects.filter(book_id = 1)
<QuerySet [<PersonInfo: 郭靖>, <PersonInfo: 黄蓉>, <PersonInfo: 黄药师>, <PersonInfo: 欧阳锋>, <PersonInfo: 梅超风>]>
>>>