Django框架05 /orm单表操作
Django框架05 /orm单表操作
1. orm使用流程
配置mysql
# django 连接mysql,settings配置文件中
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'orm02',
'USER':'root',
'PASSWORD':'123',
'HOST':'127.0.0.1',
'PORT':3306,
}
}
用pymysql替换mysqldb
# 项目文件夹下的init文件中写上下面内容,用pymysql替换mysqldb
import pymysql
pymysql.install_as_MySQLdb()
models文件中创建一个类
class UserInfo(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=10)
bday = models.DateField()
checked = models.BooleanField() BooleanField() # 不能设置空值,只能设置默认值
执行数据库同步指令
python manage.py makemigrations
python manage.py migrate # 执行数据库同步指令,添加字段的时候别忘了,该字段不能为空,所有要么给默认值,要么设置它允许为空 null=True
创建记录(实例一个对象,调用save方法)
from app01 import models def query(request):
# 创建一条记录,增
new_obj = models.UserInfo(
id=2,
name='张三',
bday='2019-09-27',
checked=1,
)
new_obj.save()
# 翻译成sql语句,然后调用pymysql,发送给服务端
# insert into app01_userinfo values(2,'张三','2019-09-27',1) return HttpResponse('xxx')
orm语句执行流程
orm语句 -- sql -- 调用pymysql客户端发送sql -- mysql服务端接收到指令并执行
2. orm字段
CharField
- 字符串字段, 用于较短的字符串.
- CharField 要求必须有一个参数 maxlength, 用于从数据库层和Django校验层限制该字段所允许的最大字符数.
IntegerField
用于保存一个整数.
DecimalField
一个浮点数. 必须 提供两个参数: 参数 描述
max_digits 总位数(不包括小数点和符号)
decimal_places 小数位数 # 举例
# 要保存最大值为 999 (小数点后保存2位),要这样定义字段:
models.DecimalField(..., max_digits=5, decimal_places=2) # 要保存最大值一百万(小数点后保存10位)的话,要这样定义:
models.DecimalField(..., max_digits=17, decimal_places=10)
# max_digits大于等于17就能存储百万以上的数了
BooleanField
用 checkbox 来表示此类字段,用来存储布尔值
TextField
一个容量很大的文本字段
EmailField
判断输入的是不是一个合法的email字段,不接受 maxlength 参数.
DateField
一个日期字段, 共有下列额外的可选参数:
Argument 描述
auto_now 当对象被保存时(更新或者添加都行),自动将该字段的值设置为当前时间.
通常用于表示 "last-modified" 时间戳.
auto_now_add 当对象首次被创建时,自动将该字段的值设置为当前时间.通常用于表示对象创建时间.
DateTimeField
一个日期时间字段. 类似 DateField 支持同样的附加选项.
AutoField
一个 IntegerField, 添加记录时它会自动增长. 通常不需要直接使用这个字段;
自定义一个主键:my_id=models.AutoField(primary_key=True)
如果不指定主键的话,系统会自动添加一个主键字段到model.
URLField
用于保存 URL. 若 verify_exists 参数为 True (默认), 给定的 URL 会预先检查是否存在
即URL是否被有效装入且没有返回404响应
FileField
一个文件上传字段. 要求一个必须有的参数: upload_to, 一个用于保存上载文件的本地文件系统路径. 这个路径必须包含 strftime 注意:
在一个 model 中使用 FileField 或 ImageField 需要以下步骤:
1、在settings 文件中, 定义一个完整路径给 MEDIA_ROOT 以便让 Django在此处保存上传文件.
(出于性能考虑,这些文件并不保存到数据库.) 定义MEDIA_URL 作为该目录的公共 URL. 要确保该目录对
WEB服务器用户帐号是可写的.
2、在model 中添加 FileField 或 ImageField, 并确保定义了 upload_to 选项,以告诉 Django
使用 MEDIA_ROOT 的哪个子目录保存上传文件.你的数据库中要保存的只是文件的路径(相对于 MEDIA_ROOT).
ImageField
它有两个可选参数:height_field和width_field,
类似 FileField, 不过要校验上传对象是否是一个合法图片.
如果提供这两个参数,则图片将按提供的高度和宽度规格保存.
3. orm参数
null
如果为True,Django 将用NULL 来在数据库中存储空值。 默认值是 False.
blank
如果为True,该字段允许不填。默认为False。
要注意,这与 null 不同。null纯粹是数据库范畴的,而 blank 是数据验证范畴的。
如果一个字段的blank=True,表单的验证将允许该字段是空值。如果字段的blank=False,该字段就是必填的。
default
字段的默认值。可以是一个值或者可调用对象。如果可调用 ,每有新对象被创建它都会被调用,如果你的字段没有设置可以为空,那么将来如果我们后添加一个字段,这个字段就要给一个default值
primary_key
如果为True,那么这个字段就是模型的主键。如果你没有指定任何一个字段的primary_key=True,
Django 就会自动添加一个IntegerField字段做为主键,所以除非你想覆盖默认的主键行为,
否则没必要设置任何一个字段的primary_key=True。
unique
如果该值设置为 True, 这个数据字段的值在整张表中必须是唯一的
choices
由二元组组成的一个可迭代对象(例如,列表或元组),用来给字段提供选择项。 如果设置了choices ,默认的表单将是一个选择框而不是标准的文本框,而且这个选择框的选项就是choices 中的选项。
auto_now_add
配置auto_now_add=True,创建数据记录的时候会把当前时间添加到数据库。
auto_now
配置上auto_now=True,每次更新数据记录的时候会更新该字段,标识这条记录最后一次的修改时间。
DatetimeField、DateField、TimeField这个三个时间字段,都可以设置auto_now_add、auto_now属性。
时间问题:auto_now_add/auto_now
models.UserInfo.objects.create(
name='张三',
bday=current_date, # 直接插入时间没有时区问题
checked=0
) now = models.DateTimeField(auto_now_add=True,null=True)
# 如果自动来插入时间,就会有时区的问题,auto_now_add创建记录时自动添加当前创建记录时的时间,存在时区问题 # 解决方法:
# settings配置文件中将USE_TZ的值改为False
# USE_TZ = True
USE_TZ = False # 告诉mysql存储时间时按照当地时间来存,不要用utc时间
# 使用pycharm的数据库客户端的时候,时区问题要注意
4. orm单表简单增/删/改
增:
# 方式1:
new_obj = models.UserInfo(
id=2,
name='张三',
bday='2019-09-27',
checked=1,
)
new_obj.save() # 方式2:
# ret 是创建的新的记录的model对象
ret = models.UserInfo.objects.create(
name='张三',
bday='2019-08-07',
checked=0
) print(ret) # UserInfo object
print(ret.name) # '张三'
print(ret.bday) # '2019-08-07'
批量增加/bulk_create
book_list = []
for i in range(10):
bk_obj = models.Book(
name='张三%s'%i,
addr='北京%s'%i
)
book_list.append(bk_obj) models.Book.objects.bulk_create(book_list) # 批量插入,速度快
删
# 简单查询:filter()
# 结果是queryset类型的数据里面是一个个的model对象,类似于列表 models.UserInfo.objects.filter(id=6).delete() # queryset对象调用
models.UserInfo.objects.filter(id=6)[0].delete() # model对象调用
改
# 方式1:update
models.UserInfo.objects.filter(id=2).update(
name='李四',
checked = 0,
) # 错误示例,model对象不能调用update方法
models.UserInfo.objects.filter(id=2)[0].update(
name='李四',
checked = 0,
)
# 方式2
ret = models.UserInfo.objects.filter(id=2)[0]
ret.name = '李四'
ret.checked = 1
ret.save() nowtime = models.DateTimeField(auto_now=True,null=True)
# 注意:
# 更新时的auto_now参数
# 更新记录时,自动更新时间,创建新纪录时也会帮你自动添加创建时的时间,但是在更新时只有使用方式2的save方法才能自动更新时间,有缺陷
5. orm单表查询
5.1 查询api
all()
- 查询所有结果,结果是queryset类型
ret = models.Books.objects.all()
print(ret) < QuerySet[ < Books: Books object >, < Books: Books object >] >
filter(**kwargs) -- 条件查询
- 包含与所给筛选条件相匹配的对象,结果也是queryset类型
- 如果没有写查询条件会获取所有数据,queryset类型的数据还能够继续调用fitler方法
- 查询条件不能匹配到数据时,不会报错,返回一个空的queryset,<QuerySet []>
ret = models.Books.objects.filter(name='linux')
print(ret)
<QuerySet [<Books: Books object>, <Books: Books object>]> #多条件查询用,隔开--是and的关系
ret = models.Books.objects.filter(name='linux',price=113)
print(ret)
<QuerySet [<Books: Books object>, <Books: Books object>]>
get(kwargs) ***
- 返回与所给筛选条件相匹配的对象,不是queryset类型,是model对象
- 返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。捕获异常try。
ret = models.Books.objects.get(id=5)
print(ret)
Books object # 报错原因:
# 1. 查不到数据会报错 :Book matching query does not exist.
# 2. 超过一个就报错 :returned more than one Book -- it returned 13!
exclude(**kwargs) -- 排除
- 排除的意思,它包含了与所给筛选条件不匹配的对象,没有不等于的操作,用这个exclude,返回值是queryset类型
- model对象和queryset对象都可以调用
Book.objects.exclude(id=6) # 返回id不等于6的所有的对象
Book.objects.all().exclude(id=6) # 在queryset基础上调用
# model对象调用:
ret = models.Books.objects.exclude(name='python')
print(ret) <QuerySet [<Books: Books object>, <Books: Books object>, <Books: Books object>]> # queryset对象调用:
ret = models.Books.objects.all().exclude(name='python')
print(ret) <QuerySet [<Books: Books object>, <Books: Books object>, <Books: Books object>]>
order_by(*field) -- 排序
- queryset类型的数据来调用,对查询结果排序,默认是按照id来升序排列的,返回值还是queryset类型
- 两种方式改变升序和降序:
- 1.在传入fields参数的时候,在参数前加-代表降序,不加代表升序.
- 2.在fields的后面,再加上方法进行改变, asc( )代表升序 ,desc( )代表降序.
- 切忌:
- 不要在一个order_by后又加一个order_by,后面的会覆盖掉之前的查询结果.
升序排序:
models.Book.objects.all().order_by('price') # 默认是按照price升序排列 降序排序:
models.Book.objects.all().order_by('-price') # 按照字段降序排列,就写个负号就行了 多条件排序:
models.Book.objects.all().order_by('price','id') # 是多条件排序,按照price进行升序,price相同的数据,按照id进行升序
reverse() -- 反转
- queryset类型的数据来调用,返回值还是queryset类型
- 对查询结果反向排序,只适用于已经默认排序或者使用order_by排序过后的查询集,如果未排序,则没有效果.
count() -- 计数、统计返回结果的数量
- queryset类型的数据来调用,返回数据库中匹配查询(QuerySet)的对象数量
first()
- queryset类型的数据来调用,得到的都是model对象,返回第一条记录
Book.objects.all()[0] = Book.objects.all().first()
# 得到的都是model对象,不是queryset
last()
- queryset类型的数据来调用,返回最后一条记录
exists() -- 判断返回结果是否有数据
- queryset类型的数据来调用,如果QuerySet包含数据,就返回True,否则返回False,效率高
models.Book.objects.all().exists() # exists() 括号内不能放数据 # 翻译成的sql是SELECT (1) AS `a` FROM `app01_book` LIMIT 1,
# 就是通过limit 1,取一条来看看是不是有数据
values(*field)
- queryset类型的数据来调用,返回一个ValueQuerySet——一个特殊的QuerySet
- model的实例化对象来调用,而是一个可迭代的字典序列,只要是返回的queryset类型,就可以继续链式调用queryset类型的其他的查找方法,其他方法也是一样的。
# 示例一:
ret = models.Books.objects.all().values('name')
print(ret) <QuerySet [{'name': 'python'}, {'name': 'linux'}, {'name': 'Go'}]> # 示例二:
ret = models.Books.objects.values('name')
print(ret) <QuerySet [{'name': 'python'}, {'name': 'python'}, {'name': 'linux'}, {'name': 'python'}, {'name': 'linux'}, {'name': 'Go'}]>
# 调用values或者values_list的对象是objects控制器,那么返回所有数据
values_list(*field)
- 它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列
ret = models.Books.objects.all().values_list('name')
print(ret)
<QuerySet [('python',), ('linux',), ('Go',)]>
distinct() -- 去重、配置values和values_list来使用
- distinct()括号里不能加去重的条件
- values和values_list得到的queryset类型的数据来调用,从返回结果中剔除重复纪录
ret = models.Books.objects.values('name').distinct()
print(ret) <QuerySet [{'name': 'python'}, {'name': 'linux'}, {'name': 'Go'}]> # 错误示例:
ret = models.Books.objects.all().distinct()
print(ret)
<QuerySet [<Books: python>, <Books: python>, <Books: linux>, <Books: python>, <Books: linux>, <Books: Go>]> # 注意:
# 不在values()、values_list()后面使用没有意义,因为要是所有的内容全相同才会去重
5.2 基于双下划线的模糊查询 / filter双下划线查询
在里边:
__in
Book.objects.filter(price__in=[100,200,300])
# price值等于这三个里面的任意一个的对象
大于:
__gt
Book.objects.filter(price__gt=100) # 大于
大于等于:
__gte
Book.objects.filter(price__gte=100)
# 大于等于,别写price>100,这种参数不支持
小于:
__lt
Book.objects.filter(price__lt=100) # 小于
小于等于:
__lte
Book.objects.filter(price__lte=100) # 小于
# 小于等于,别写price>100,这种参数不支持
包含:
__contains
Book.objects.filter(title__contains="python")
# title值中包含python的
包含,不区分大小写:
__icontains
Book.objects.filter(title__icontains="python")
# 不区分大小写
以什么开头:
__startswith
Book.objects.filter(title__startswith="py")
# 以什么开头
以什么开头,不区分大小写:
__istartswith
Book.objects.filter(title__istartswith="py")
# 不区分大小写
日期相关
# 筛选日期
Book.objects.filter(pub_date='2012-9-12') # 筛选年份
Book.objects.filter(pub_date__year=2012)
# 筛选大于该年份的
Book.objects.filter(pub_date__ year_gt='2018') # 大于2018年的、2018数字类型也可以 # 筛选某年某月
Book.objects.filter(pub_date__year='2019' ,pub_ date__ month='8') # 筛选某年某月某日
Book.objects.filter(pub_date__ year='2019' ,pub_date__month='8',pub_date__day='01')
判断是否为空
models.Book.objects.filter(publish_date__isnull=True)
# 这个字段值为空的那些数据
总结:
新增字段(必须设置可以为空或者设置默认值)
UTC时间格式格林尼治时间
model对象不能调用update方法
USE_TZ = False
orm整体流程代码示例
orm > settings.py
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'orm1',
'HOST':'127.0.0.1',
'PORT':3306,
'USER':'root',
'PASSWORD':'123'
}
} # 设置mysql默认使用当地时间
USE_TZ = False # 不是跨时区的应用,不需要考虑时区问题,就将这个值改为False
# mysql是对时区不敏感,django往mysql里面出数据的时候
# 如果这里的值为True,那么将让mysql强制使用UTC时间
# 那么存储时间后,当查询的时候,就会发现,时间晚了8小时
orm1 > __init__.py
import pymysql
pymysql.install_as_MySQLdb()
models.py
from django.db import models class Userinfo(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=16)
register_time = models.DateField(null=True)
# auto_now_add=True 修改记录不会改变,只会在添加数据的时候添加时间
update_time = models.DateTimeField(auto_now=True,null=True)
# auto_now=True, 修改记录用方式一/update不会改变、用方式二/ret.save()会更新
checked = models.BooleanField(default=0)
views.py
from django.shortcuts import render,HttpResponse
from app01 import models
from datetime import datetime def query(request):
# 创建记录
# 方式一
current_time = datetime.now()
new_obj = models.Userinfo(
id = 1,
name = 'ZHANGSAN'
)
new_obj.save() # 方式二
ret =models.Userinfo.objects.create(
name='ZHANGSAN',
register_time='2019-8-8',
update_time='2019-8-10 12:12:12',
checked=1, )
ret = models.Userinfo.objects.filter(name='ZHANGSAN')
print(ret) # 删除
ret = models.Userinfo.objects.filter(id=7)[0].delete()
print(ret)
# 将符合条件的第一条记录删除 ret = models.Userinfo.objects.filter(id=7).delete()
print(ret)
# 将符合条件的所有记录删除
# 注意:filter搜索出来的是queryset类型的列表:queryset<[对象1,对象2,对象3]> # 修改
# 方式一
models.Userinfo.objects.filter(id=1).update(
name='ZHANGSAN',
checked=1,
register_time = '2019-1-1',
update_time = '2020-06-03',
) # 方式二
ret = models.Userinfo.objects.filter(id=1)[0]
ret.name='LISI'
ret.save()
return HttpResponse('OK')
# 注意:model对象不能调用update()方法
单表查询返回models对象的方法
1.get(**kwargs)
2.create(**kwargs)
3.count()
# 该方法返回与之匹配的数据库中对象的个数,并且有一个最大的特点,永远不会返回异常
4.first()
5.last()
6.get_or_create(defaults=None,**kwargs)
# 如果存在则返回查找的对象,如果不存在则创建一个新的对象并且保存.
7.update_or_create(defaults= None,** kwargs)
# 该方法查找defaults中的对象,如果找到则更新数值,如果没有,则创建对象.
单表查询返回queryset对象的方法
1.all()
2.filter(**kwargs)
3.exclude(**kwargs)
4.order_by( *fields)
5.reverse()
6.distinct()
7.values(*fields,)
8.values_list(*fields,)
Django框架05 /orm单表操作的更多相关文章
- django框架基础-ORM单表操作-长期维护
############### 单表操作-添加数据 ################ import os if __name__ == '__main__': os.environ.set ...
- Django框架06 /orm多表操作
Django框架06 /orm多表操作 目录 Django框架06 /orm多表操作 1. admin相关操作 2. 创建模型 3. 增加 4. 删除 5. 修改 6. 基于对象的跨表查询 7. 基于 ...
- Django之模型---ORM 单表操作
以上一随笔中创建的book表为例讲解单表操作 添加表记录 方式一 # create方法的返回值book_obj就是插入book表中的python葵花宝典这本书籍纪录对象 book_obj=Book.o ...
- django框架基础-ORM跨表操作-长期维护
############### 一对一跨表查询 ################ import os if __name__ == '__main__': os.environ.setde ...
- Django模型层之单表操作
Django模型层之单表操作 一 .ORM简介 我们在使用Django框架开发web应用的过程中,不可避免地会涉及到数据的管理操作(如增.删.改.查),而一旦谈到数据的管理操作,就需要用到数据库管理软 ...
- day 69 Django基础五之django模型层(一)单表操作
Django基础五之django模型层(一)单表操作 本节目录 一 ORM简介 二 单表操作 三 章节作业 四 xxx 一 ORM简介 MVC或者MVC框架中包括一个重要的部分,就是ORM,它实现 ...
- day 55 Django基础五之django模型层(一)单表操作
Django基础五之django模型层(一)单表操作 本节目录 一 ORM简介 二 单表操作 三 章节作业 四 xxx 一 ORM简介 MVC或者MVC框架中包括一个重要的部分,就是ORM,它 ...
- day 46 Django 学习3 数据库单表操作以及反向解析
前情提要: Django 已经学了不少了, 今天学习链接数据库的操作.以及相关的反向解析等 一:反向解析 1:反向解析模板层 跳转时设定url会随着前面的路由改变而改变 2:反向解析之 ...
- day59——orm单表操作
day59 orm单表操作 对象关系映射(object relational mapping) orm语句 -- sql -- 调用pymysql客户端发送sql -- mysql服务端接收到指令并执 ...
随机推荐
- Java 内存溢出(java.lang.OutOfMemoryError)的常见情况和处理方式
导致OutOfMemoryError异常的常见原因有以下几种: 内存中加载的数据量过于庞大,如一次从数据库取出过多数据: 集合类中有对对象的引用,使用完后未清空,使得JVM不能回收: 代码中存在死循环 ...
- 前台页面id为空--驼峰命名映射
错误: 前台页面id为空,或其他数据映射问题(方案2) 原因: java的bean类属性和数据库字段命名不一致,查询的时候就不能把数据封装进bean类里, 在数据库字段命名规范中,通常使用下划线“_ ...
- localStorage. sessionStorage、 Cookie不共同点:(面试题)
●存储大小的不同: localStorage的大小一般为5M sessionStorage的大小一般为5M cookies的大小一般为4K ●有效期不同: 1.localStorage的有效期为永久有 ...
- JavaScript DOM 注册事件
一个HTML是一个DOM树,每一个节点都是DOM对象,整个HTML其实也是一个DOM对象,根节点是<html>; 在HTML页面初始化的时候,JavaScript会自动帮DOM对象注册消息 ...
- 虚拟机 VMware 设置VMWARE通过桥接方式使用主机无线网卡上网
环境:WIN7旗舰版,台式机,U盘无线上网卡. 虚拟软件:VMware9.0,虚拟系统:CentOS6.4 需要实现虚拟机以独立机形式工作和上网. 先介绍一下VMware网络设置的三种方式 1 Hos ...
- TestNG配合catubuter统计单元测试的代码覆盖率
build-testNG.xml对应的ant脚本为 <?xml version="1.0" encoding="UTF-8"?> <proje ...
- web 基础(一) HTML
web 基础(一) HTML 与 XHTML 一.HTML介绍 HTML( Hyper Text Markup Language)指的是超文本标记语言,是用来描述网页的一种语言.它包括一系列标签.通过 ...
- 暑假集训日记Day xx
Day 1 6.23 今天算是第一天吧 (毕竟昨天被迫做了半天苦力) 充实而丰满的一天:上午做题 下午讲题 晚上改错(考试是原题和我会做有什么关系吗) 早起跑操还阔以(比之前距离短就很快乐) 然后练了 ...
- 入门大数据---Python基础
前言 由于AI的发展,包括Python集成了很多计算库,所以淡入了人们的视野,成为一个极力追捧的语言. 首先概括下Python中文含义是蟒蛇,它是一个胶水语言和一个脚本语言,胶水的意思是能和多种语言集 ...
- Python实用笔记 (2)list和tuple
list 这就是一个列表: classmates = ['Michael', 'Bob', 'Tracy'] //内部数据类型可以不同 同样len()函数可以获取长度: len(classmates) ...