Django1.8.2 中文文档: Django1.8.2 中文文档 https://yiyibooks.cn/xx/django_182/index.html 或者 https://yiyibooks.cn/xx/django_182/index.html
项目准备
注释: 关于项目准备, 其实和后面的大部分内容都无关, 或者说, 可以不看, 但为了自己和他人更好的体验, 还是放上去.
创建项目
1. 创建项目 test1000;
2. 创建应用 booktest;
注册应用:
- INSTALLED_APPS = [
- 'booktest.apps.BooktestConfig',
- ]
3. 创建数据库
create database test1000 default charset utf8;
在 settings 文件下配置数据库
- DATABASES = {
- 'default': {
- # 'ENGINE': 'django.db.backends.sqlite3',
- 'ENGINE': 'django.db.backends.mysql',
- # 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
- 'NAME': 'test1000', # 使用的数据库的名字, 数据库必须手动创建
- 'USER': 'root', # 链接 MySQL 的用户名
- 'PASSWORD': 'root', # 对应用户的密码
- 'HOST': '127.0.0.1', # 指定 MySQL 数据库所在电脑 ip
- 'PORT': '3306', # MySQL 服务的端口号
- }
- }
数据库配置
4. 在 test1000/__init__.py 中加如下内容:
注意: 如果没有 pymysql 需要先 pip install
- import pymysql
- pymysql.install_as_MySQLdb()
5. 定义模型类
- class BookInfo(models.Model):
- """图书模型类"""
- # 图书名称
- btitle = models.CharField(max_length=20)
- # 出版日期
- bpub_date = models.DateField()
- # 阅读量
- bread = models.IntegerField(default=0)
- # 评论量
- bcomment = models.IntegerField(default=0)
- # 删除标记
- isDelete = models.BooleanField(default=False)
- class HeroInfo(models.Model):
- """图书模型类"""
- # 英雄名
- hname = models.CharField(max_length=20)
- # 性别
- hgender = models.BooleanField(default=False)
- # 备注
- hcomment = models.CharField(max_length=200)
- # 关系属性
- bhbook = models.ForeignKey(to="BookInfo")
- # 删除标记
- isDelete = models.BooleanField(default=False)
定义图书和英雄类
生成迁移数据
- python manage.py makemigrations
- python manage.py migrate
插入数据
- INSERT INTO `test1000`.`booktest_bookinfo` (`btitle`, `bpub_date`, `bread`, `bcomment`, `isDelete`) VALUES ('射雕英雄传', '1980-05-01', 12, 34, 0)
- INSERT INTO `test1000`.`booktest_bookinfo` (`btitle`, `bpub_date`, `bread`, `bcomment`, `isDelete`) VALUES ('天龙八部', '1986-07-24', 36, 40, 0)
- INSERT INTO `test1000`.`booktest_bookinfo` (`btitle`, `bpub_date`, `bread`, `bcomment`, `isDelete`) VALUES ('笑傲江湖', '1995-12-24', 20, 80, 0)
- INSERT INTO `test1000`.`booktest_bookinfo` (`btitle`, `bpub_date`, `bread`, `bcomment`, `isDelete`) VALUES ('雪山飞狐', '1987-11-11', 58, 24, 0)
- INSERT INTO `test1000`.`booktest_heroinfo` (`hname`, `hgender`, `hbook_id`, `hcomment`, `isDelete`) VALUES
- ('郭靖',1,1,'降龙十八掌',0),
- ('黄蓉',0,1,'打狗棍法',0),
- ('黄药师',1,1,'弹指神通',0),
- ('欧阳锋',1,1,'蛤蟆功',0),
- ('梅超风',0,1,'九阴白骨爪',0),
- ('乔峰',1,2,'降龙十八掌',0),
- ('段誉',1,2,'六脉神剑',0),
- ('虚竹',1,2,'天山六阳掌',0),
- ('王语嫣',0,2,'神仙姐姐',0),
- ('令狐冲',1,3,'独孤九剑',0),
- ('任盈盈',0,3,'弹琴',0),
- ('岳不群',1,3,'华山剑法',0),
- ('东方不败',0,3,'葵花宝典',0),
- ('胡斐',1,4,'胡家刀法',0),
- ('苗若兰',0,4,'黄衣',0),
- ('程灵素',0,4,'医术',0),
- ('袁紫衣',0,4,'六合拳',0);
插入数据
6.index 页面显示书籍
创建模板 templates 文件夹;
去 settings 里面注册模板文件夹;
创建 index 页面;
编写 index 页面, 使用 ul 渲染书籍数据;
给 index 添加 a 标签指向 create 路由;
- <h2>index 页面</h2>
- <a href="/create">添加</a>
- <ul>
- {% for book in books %}
- <li>{{ book.btitle }}</li>
- {% endfor %}
- </ul>
index.HTML
编写函数, 使用模板渲染显示书籍的页面
编写 index 函数, 返回页面渲染;
- def index(request):
- """显示书籍"""
- # 获取所有书名
- books = models.BookInfo.objects.all()
- # 使用模板渲染书籍
- return render(request, "booktest/index.html", {"books": books})
index 函数
进行 url 匹配;
将路由导向 booktest 里面的路由文件;
- from django.conf.urls import include, url
- from django.contrib import admin
- urlpatterns = [
- url(r'^admin/', admin.site.urls),
- url(r'^', include('booktest.urls')), # 包含 booktest 应用中的路由文件
- ]
test1000/url.py
主要路由统一写在此处, 不再重复写
- # booktest/url.py
- from django.conf.urls import url
- from booktest import views
- urlpatterns = [
- url(r'^index/', views.index), # 显示图书信息
- url(r'^create/', views.create), # 添加一本书籍
- url(r'^delete(\d+)/', views.delete), # 删除一本书籍
- url(r'^areas/$', views.areas), # 自关联案例
- ]
7. 进行书籍添加处理
编写 create 函数, 创建 bookinfo 对象, 保存数据, 导入 redirect, 给 create 函数返回 redirect 到 / index 页面;
- def create(request):
- """增加一本书籍"""
- # 1. 创建 bookinfo 对象
- b = models.BookInfo()
- b.btitle = "流星蝴蝶剑"
- b.bpub_date = date(1990, 1, 1)
- # 2. 保存进数据库
- b.save()
- # 3. 返回应答, 让浏览器再访问首页
- # return HttpResponse("ok")
- return redirect('/index')
create 函数
给 create 函数进行路由匹配;
8. 进行删除书籍处理
给图书后面添加删除链接, 链接应加上书籍 id;
- <a href="/create">添加</a>
- <ul>
- {% for book in books %}
- <li>{{ book.btitle }}--<a href="/delete{{ book.id }}">删除</a></li>
- {% endfor %}
- </ul>
编写 delete 函数;
- def delete(request, bid):
- """删除一本书籍"""
- # 1. 获取书籍对象
- book = models.BookInfo.objects.get(id=bid)
- # 2. 删除书籍
- book.delete()
- # 3. 重定向
- return redirect('/index')
delete 函数
进行路由匹配, 注意路由匹配时应接收书籍 id; 即:
url(r'^delete(\d+)/', views.delete), # 删除一本书籍
a 标签中 url 的 /
<a href="/create">添加</a>
a 标签记得前面统一加上 /;
没加斜杠的, 表示在当前的路由下进行拼接, 比如现在在是 http://127.0.0.1:8000/index, 路由是 create, 那么就会拼接成 / index/create;
而加了斜杠就不会出现这个问题, 斜杠表示 http://127.0.0.1:8000/, 会直接拼接到根路由下;
Django ORM
O:(objects)->类和对象.
R:(Relation)->关系, 关系数据库中的表格.
M:(Mapping)->映射.
ORM 框架的功能:
a)能够允许我们通过面向对象的方式来操作数据库.
b)可以根据我们设计的模型类帮我们自动生成数据库中的表格.
c) 通过方便的配置就可以进行数据库的切换.
字段属性和选项
模型类属性命名限制
1)不能是 python 的保留关键字.
2)不允许使用连续的下划线, 这是由 django 的查询方式决定的.
3)定义属性时需要指定字段类型, 通过字段类型的参数指定选项, 语法如下: 属性名 = models. 字段类型(选项)
字段类型
使用时需要引入 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=None, decimal_places=None) | 十进制浮点数。 参数 max_digits 表示总位数。参数 decimal_places 表示小数位数。 |
FloatField | 浮点数。参数同上,精确度不如上面的。 |
FileField | 上传文件字段。 |
ImageField | 继承于 FileField,对上传的内容进行校验,确保是有效的图片。 |
DateField | 日期。年月日 < br ztid="304" ow="0" oh="0"> 参数 auto_now 表示每次保存对象时,自动设置该字段为当前时间,用于 "最后一次修改" 的时间戳,它总是使用当前日期,默认为 false。 |
TimeField | 时间,参数同 DateField。小时分秒 |
DateTimeField | 日期时间,参数同 DateField。年月日时分秒 |
选项
通过选项实现对字段的约束, 选项如下:
选项名 | 描述 |
default | 默认值。 |
primary_key | 若为 True,则该字段会成为模型的主键字段,默认值是 False,一般作为 AutoField 的选项使用。 |
unique | 如果为 True, 这个字段在表中必须有唯一值,默认值是 False。 |
db_index | 若值为 True, 则在表中会为此字段创建索引,默认值是 False。 |
db_column | 字段的名称,如果未指定,则使用属性的名称。 |
null | 如果为 True,表示允许为空,默认值是 False。 |
blank | 如果为 True,则该字段允许为空白,默认值是 False。 |
对比: null 是数据库范畴的概念, blank 是表单验证证范畴的.
经验: 当修改模型类之后, 如果添加的选项不影响表的结构, 则不需要重新做迁移, 例如商品的选项中 default 和 blank 不影响表的结构;
如果想要更深入的了解模型的选型和字段, 建议看官方文档, 百度 Django1.8.2. 中文文档即可.
单表查询
配置 MySQL 的日志文件
让其产生 MySQL.log, 即是 MySQL 的日志文件, 里面记录了对 MySQL 数据库的操作记录.
1). 使用下面的命令打开 MySQL 的配置文件, 取消 68,69 行的注释, 然后保存.
sudo vi /etc/MySQL/MySQL.conf.d/mysqld.cnf
2). 重启 MySQL 服务, 就会产生 MySQL 日志文件.
sudo service MySQL restart
3). 打开 MySQL 的日志文件
/var/log/MySQL/MySQL.log # MySQL 日志文件所在位置
4). 使用下面命令实时查看 MySQL 文件的内容
sudo tail -f /var/log/MySQL/MySQL.log
查询函数
通过模型类. object 属性可以调用如下函数, 实现对模型类对应的数据表的查询;
注意, 查询集里面, 还可以再次调用一下函数进行处理, 即如果你通过 filter 等函数查询出来的数据, 还可以调用 filter 等函数进行处理;
函数名 | 功能 | 返回值 | 备注 |
get() | 返回表中满足条件的一条且只能有一条数据 | 返回对象; | 如果查到多条数据,则抛异常:MultipleObjectsReturned |
all() | 返回模型类对应表格中的所有数据。 | QuerySet 类型 | 查询集 |
filter() | 返回满足条件的数据 | QuerySet 类型 | 参数写查询条件; 条件格式:模型类属性名__条件名 = 值。 |
exclude | 返回不满足条件的数据 | QuerySet 类型 | 参数写查询条件; |
order_by | 对查询结果进行排序。 | QuerySet 类型 | 参数中写根据哪些字段进行排序。 |
filter 方法示例:
1. 判等 exact.
例: 查询编号为 1 的图书.
- BookInfo.objects.get(id=1)
- BookInfo.objects.get(id__exact=1)
2. 模糊查询
例: 查询书名包含'传'的图书. contains
BookInfo.objects.filter(btitle__contains='传')
例: 查询书名以'部'结尾的图书 endswith 开头: startswith
BookInfo.objects.filter(btitle__endswith='部')
3. 空查询 isnull
select * from booktest_bookinfo where title is not null;
例: 查询书名不为空的图书. isnull
BookInfo.objects.filter(btitle__isnull=False)
4. 范围查询 in
select * from booktest_bookinfo where id in (1,3,5)
例: 查询编号为 1 或 3 或 5 的图书.
BookInfo.objects.filter(id__in = [1,3,5])
5. 比较查询
gt(greate than) 大于
lt(Less than) 小于
gte(equal) 大于等于
lte 小于等于
例: 查询编号大于 3 的图书.
BookInfo.objects.filter(id__gt = 3)
6. 日期查询
例: 查询 1980 年发表的图书.
BookInfo.objects.filter(bpub_date__year=1980)
例: 查询 1980 年 1 月 1 日后发表的图书.
- from datetime import date
- BookInfo.objects.filter(bpub_date__gt = date(1980,1,1))
exclude 方法示例:
例: 查询 id 不为 3 的图书信息.
BookInfo.objects.exclude(id=3)
order_by 示例方法:
作用: 进行查询结果进行排序
降序 (.all() 可以省略)
- # 例 1: 查询所有图书信息, 按照 id 从小到大顺序进行排序;
- BookInfo.objects.all().order_by('id') # 按照升序排序
- # 查询所有图书信息, 按照 id 从大到小顺序进行排序;
- BookInfo.objects.all().order_by('-id') # 按照降序排序
- # 把 id 大于 3 的图书信息按阅读量从大到小排序显示.
- BookInfo.objects.filter(id__gt=3).order_by('-bread') # 把 id 大于 3 的图书信息按阅读量从大到小排序显示.
Q 对象
作用: 用于查询时条件之间的逻辑关系. not and or, 可以对 Q 对象进行 &|~ 操作.
使用之前需要先导入:
from django.db.models import Q
例: 查询 id 大于 3 且阅读量大于 30 的图书的信息.
- BookInfo.objects.filter(id__gt=3, bread__gt=30)
- BookInfo.objects.filter(Q(id__gt=3)&Q(bread__gt=30))
例: 查询 id 大于 3 或者阅读量大于 30 的图书的信息.
BookInfo.objects.filter(Q(id__gt=3)|Q(bread__gt=30))
例: 查询 id 不等于 3 图书的信息.
BookInfo.objects.filter(~Q(id=3))
F 对象
作用: 用于类属性之间的比较. 比如要查询评论量大于阅读量的文章书籍时就可以使用;
使用之前需要先导入:
from django.db.models import F
例: 查询图书阅读量大于评论量图书信息.
BookInfo.objects.filter(bread__gt=F('bcomment'))
例: 查询图书阅读量大于 2 倍评论量图书信息.
BookInfo.objects.filter(bread__gt=F('bcomment')*2)
聚合函数
作用: 对查询结果进行聚合操作.
- sum
- count
- avg
- max
- min
aggregate: 调用这个函数来使用聚合. 返回值是一个字典
使用前需先导入聚合类:
from django.db.models import Sum,Count,Max,Min,Avg
例: 查询所有图书的数目.
- BookInfo.objects.all().aggregate(Count('id'))
- {
- 'id__count': 5
- }
例: 查询所有图书阅读量的总和.
- BookInfo.objects.aggregate(Sum('bread'))
- {
- 'bread__sum': 126
- }
count 函数
返回一个数字
作用: 统计满足条件数据的数目.
例: 统计所有图书的数目.
- BookInfo.objects.all().count()
- BookInfo.objects.count()
结果: 5
例: 统计 id 大于 3 的所有图书的数目.
BookInfo.objects.filter(id__gt=3).count()
查询相关函数小结
get: 返回一条且只能有一条数据, 返回值是一个对象, 参数可以写查询条件.
all: 返回模型类对应表的所有数据, 返回值是 QuerySet.
fiter: 返回满足条件的数据, 返回值是 QuerySet, 参数可以写查询条件.
exclude: 返回不满足条件的数据, 返回值是 QuerySet, 参数可以写查询条件.
order_ by: 对查询结果进行排序, 返回值是 QuerySet, 参数中写排序的字段.
注意:
1. get, flter,exclude 函数中可以写查询条件, 如果传多个参数, 条件之间代表且的关系.
2. all, fiter, exclude, order. by 函数的返回值是 QuerySet 类的实例对象, 叫做查询集.
from diango.db.models import F,Q Sum,Count Avg, Max,Min
F 对象: 用于类属性之间的比较.
Q 对象: 用于条件之间的逻辑关系.
aggregate: 进行聚合操作, 返回值是一个字典, 进行聚合的时候需要先导入聚合类.
count: 返回结果集中数据的数目, 返回值是一个数字.
注意:
对一个 QuerySet 实例对象, 可以继续调用上面的所有函数.
参考文档:
http://python.usyiyi.cn/translate/django_182/ref/models/querysets.html
查询集
all, filter, exclude, order_by 调用这些函数会产生一个查询集, QuerySet 类对象可以继续调用上面的所有函数.
查询集特性
1)惰性查询: 只有在实际使用查询集中的数据的时候才会发生对数据库的真正查询.
2)缓存: 当使用的是同一个查询集时, 第一次的时候会发生实际数据库的查询, 然后把结果缓存起来, 之后再使用这个查询集时, 使用的是缓存中的结果.
限制查询集
可以对一个查询集进行取下标或者切片操作来限制查询集的结果.
对一个查询集进行切片操作会产生一个新的查询集, 下标不允许为负数.
取出查询集第一条数据的两种方式:
方式 & nbsp; | 说明 |
b[0] | 如果 b[0] 不存在,会抛出 IndexError 异常 |
b[0:1].get() | 如果 b[0:1].get() 不存在,会抛出 DoesNotExist 异常。 |
exists: 判断一个查询集中是否有数据. True False
- books = BookInfo.objects.all()
- books1 = books[0:0]
- book.exists()
- # True
- book1.exists()
- # False
来源: https://www.cnblogs.com/yifchan/p/python-1-25.html