day58
day58
1阉割模式
没设置,设置了10个,用户写100个竟然可以存的进去,而且把后面90个阉割了,不符合要求
所以,必须设置阉割模式
1.2 会话
发送命令,回复响应叫会话
不能重启数据库,只能启用临时会话的格式
下次会话(再用),便没了
1.3 设置命令
临时设置当前对话的
公司如果没法更改全的,临时更改会话,下次重启没了
create table t1(id int primary key auto_increment, name char(5))
desc t1;
insert (into 可以不写) t1(name) values('爱心觉罗大大大');
insert into t1(name) values('爱心觉罗大大大');
mysql> select * from t1;
+----+-----------------+
| id | name |
+----+-----------------+
| 1 | 爱心觉罗大 |
+----+-----------------+
1 row in set (0.00 sec)
set sql_mode ='STRICT_TRANS_TABLES';
mysql> insert into t1(name) values('爱心觉罗大大d大');
ERROR 1406 (22001): Data too long for column 'name' at row 1
mysql> select @@sql_mode;
+---------------------+
| @@sql_mode |
+---------------------+
| STRICT_TRANS_TABLES |
+---------------------+
1 row in set (0.00 sec)
下次启用
mysql> select @@sql_mode;
+------------------------+
| @@sql_mode |
+------------------------+
| NO_ENGINE_SUBSTITUTION |
+------------------------+
1 row in set (0.00 sec)
把所有会话全设置
先加方式二,再加方式三 ,那么就可以实现下次自动阉割模式
方式二**:先执行select @@global.sql_mode,复制查询出来的值并将其中的NO_ZERO_IN_DATE,NO_ZERO_DATE删除,然后执行set global sql_mode = '修改后的值'。
此方法在当前服务中生效,重新MySQL服务后失效
**方法三**:在mysql的安装目录下,或my.cnf文件(windows系统是my.ini文件),新增 sql_mode = ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION,
添加my.cnf如下:
[mysqld]
sql_mode=ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER
然后重启mysql。
此方法永久生效.当然生产环境上是禁止重启MySQL服务的,所以采用方式二加方式三来解决线上的问题,那么即便是有一天真的重启了MySQL服务,也会永久生效了。
1.4 为什么讲阉割?
当静态文件没加载出来时,因为setting 里的 'django.contrib.staticfiles',
文件可以实现静态文件的static 然后使用makemigrations
和 migrate 更新一下 models 生成 连接
1.5 orm配置
mysql 里面通过orm创建一个表
1 mysql --- 创建一个库 rom01
2 settings -- DATABASES 这个配置
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME':'day57', # 要连接的数据库,连接前需要创建好
'USER':'root', # 连接数据库的用户名
'PASSWORD':'123', # 连接数据库的密码
'HOST':'127.0.0.1', # 连接主机,默认本级
'PORT':3306 # 端口 默认3306
}
}
3 和settings 同级目录的 init.py
import pymysql
pymysql.install_as_MySQLdb()
4 model.py
mysql表和属性
类和属性
class Book(models.Model):
id = models.AutoField(primary_key = True)
5 执行指令
python manage.py makemigrations
python manage.py migrate
开发:
专心,不专心做不了开发。别人没法打扰到自己,自己也不会打断自己。
火车上读书——毛主席
定位错误,排错能力特别强。特别认真。
学习,研究问题,记录错误。
2 程序增删改查
2.2 查看的语句(了解)
# from django.db import connection # connection管道,
# # conn = pymysql.connect()
# print(connection.queries) # orm 转换成sql语句,插入数据库
# ##通过这种方式也能查看执行的sql语句
2019-05-23 <class 'datetime.date'>
[{'sql': 'SELECT @@SQL_AUTO_IS_NULL', 'time': '0.001'}, {'sql': "INSERT INTO `app01_book` (`name`, `price`, `date`) VALUES ('三国', 100, '2019-05-23')", 'time': '0.000'}]
2.31 创建数据
方式1
from app01 import models
def show(request): # url(r'show/',views.show) date = datetime.date.today()
# print(date,type(date))
# book_obj = models.Book(name='三国',price=100,date=date)
# # book_obj = models.Book(name='水浒',price=100,date='2018-12-12')
# book_obj.save() # 往数据库里保存
方式2
# book_obj = models.Book.objects.create(
# name='三国1', price=100,date='2018-12-12'
# )
# # 封装了save
# print(book_obj) # create方法 返回的model对象
# print(book_obj.name)
2.3 简单查询
all_objs = models.Book.objects.all() #objects管理器
print(all_objs) #<QuerySet [<Book: Book object>, <Book: Book object>, <Book: Book object>]>
#<QuerySet [<Book: 水浒>, <Book: 三国>, <Book: 三国1>]>
# set是集合 一个个model对象 通过objects调用的是一个对象 操作起来像列表 索引取值
# 查询条件数据
book_obj = models.Book.objects.filter(
# pk = 1
id = 1
)
print(book_obj) #<QuerySet [<Book: 水浒>]> pk patch key 配备键
2.4 删除改
# 删除
# models.Book.objects.filter(pk=1).delete() # delete() 在queryset对象里去删 不在objects models删,防止都删了
# 更新也是
# models.Book.objects.filter(name='三国').update(
# price=222,date='2018-11-11'
# # 更新多个 ,都可以
# )
# book_obj1 = models.Book.objects.filter(price = 1000 )
# <QuerySet []> # filter 不会报错,返回的是queryset对象
# model 调用方法
# book_obj1 = models.Book.objects.get(id = 3 ) # get必须获得一条数据 如果多条 price=100 可以找到多条语句报错
# book_obj1 = models.Book.objects.get(price = 1000 ) # get必须获得一条数据 如果多条 price=100 可以找到多条语句报错
# print(book_obj1) #三国 获取单条记录 并且是model对象,并不是queryset
# 两种错误
# get 方法获取数据的两种错误,get方法必须获取一条数据
# 多和少 return 3 not exit
# book_obj1.delete() # 直接调用 也可以删除
# 谁调用 model对象和 obj 对象 都可以删除
# obj_lst = []
# for i in range(1,11):
#
# obj = models.Book(name='太白%s'%i,price=10*i,date='2019-5-%s'%i)
# obj_lst.append(obj)
#
# models.Book.objects.bulk_create(obj_lst) # 批量创建 保存save封装
# book_obj1.update(name='jin') # 'Book' object has no attribute 'update'
# update_or_create 方法 ,有更新,没有就创建
obj1,obj2 = models.Book.objects.update_or_create(
# 查 封装了 name
name='太白2', # 查询参数
defaults = { #下面需要添加的值
'price':111,
'date':'2011-1-22'
}
) #太白22--111 True 没有的
print(obj1,obj2) # 水浒2-111 false 没创建
#如果查询的数据为多条 因为调用的是get方法 少了 不报错 异常捕获crate方法
#get() returned more than one Book -- it returned 7!
2.5查询API(重点)
all queryset
filter() queryset 要想拿一个索引取值
(,)#and
get 返回models对象 多少都报错
exclude() 排除
2.6 作业需求
submit 添加一条到了数据库,数据库显示在查看书籍
删除
1. 点击添加按钮,跳转到添加页面,用户输入内容,然后点击提交按钮,将用户输入的数据保存到数据库,并自动跳转到信息展示页面
2 点击删除按钮,从数据库中删除对应的数据,并且自动跳转到信息展示页面
3 点击编辑按钮,跳转到一个新的页面,这个页面的形式和添加页面是一样的,但是里面有有默认值,然后用户点击提交,将用户提交的
修改
type = date 可以选择的 value指定默认值时,通过给加格式
给django连接mysql的指定阉割模式的配置
2.7Django设置阉割模式
一:
DATABASES = {
'default': {
.....
'OPTIONS': {
"init_command": "SET default_storage_engine='INNODB'",
#'init_command': "SET sql_mode='STRICT_TRANS_TABLES'",
}
}
}
二
DATABASES['default']['OPTIONS']['init_command'] = "SET sql_mode='STRICT_TRANS_TABLES'"
2.8 时区
mysql不识别时区,东八区 和utc的事件晚了八个小时 , 比如:存入时间12h,查的4h可到
2.9 代码
from django.shortcuts import render,HttpResponse
from app01 import models
# from app01.models import Book
import datetime
# Create your views here.
def show(request):
# 创建数据
# # 方式1
# date = datetime.date.today()
# print(date,type(date))
# book_obj = models.Book(name='三国',price=100,date=date)
# # book_obj = models.Book(name='水浒',price=100,date='2018-12-12')
#
# book_obj.save() # 往数据库里保存
#
# from django.db import connection # connection管道,
# # conn = pymysql.connect()
# print(connection.queries) # orm 转换成sql语句,插入数据库
# ##通过这种方式也能查看执行的sql语句
# 方式2
# book_obj = models.Book.objects.create(
# name='三国1', price=100,date='2018-12-12'
# )
# # 封装了save
# print(book_obj) # create方法 返回的model对象
# print(book_obj.name)
all_objs = models.Book.objects.all() #objects管理器
print(all_objs) #<QuerySet [<Book: Book object>, <Book: Book object>, <Book: Book object>]>
#<QuerySet [<Book: 水浒>, <Book: 三国>, <Book: 三国1>]>
# set是集合 一个个model对象 通过objects调用的是一个对象 操作起来像列表 索引取值
# 查询条件数据
book_obj = models.Book.objects.filter(
# pk = 1
id = 1
)
print(book_obj) #<QuerySet [<Book: 水浒>]> pk patch key 配备键
# 删除
# models.Book.objects.filter(pk=1).delete() # delete() 在queryset对象里去删 不在objects models删,防止都删了
# 更新也是
# models.Book.objects.filter(name='三国').update(
# price=222,date='2018-11-11'
# # 更新多个 ,都可以
# )
# book_obj1 = models.Book.objects.filter(price = 1000 )
# <QuerySet []> # filter 不会报错,返回的是queryset对象
# model 调用方法
# book_obj1 = models.Book.objects.get(id = 3 ) # get必须获得一条数据 如果多条 price=100 可以找到多条语句报错
# book_obj1 = models.Book.objects.get(price = 1000 ) # get必须获得一条数据 如果多条 price=100 可以找到多条语句报错
# print(book_obj1) #三国 获取单条记录 并且是model对象,并不是queryset
# 两种错误
# get 方法获取数据的两种错误,get方法必须获取一条数据
# 多和少 return 3 not exit
# book_obj1.delete() # 直接调用 也可以删除
# 谁调用 model对象和 obj 对象 都可以删除
# obj_lst = []
# for i in range(1,11):
#
# obj = models.Book(name='太白%s'%i,price=10*i,date='2019-5-%s'%i)
# obj_lst.append(obj)
#
# models.Book.objects.bulk_create(obj_lst) # 批量创建 保存save封装
# book_obj1.update(name='jin') # 'Book' object has no attribute 'update'
# update_or_create 方法 ,有更新,没有就创建
obj1,obj2 = models.Book.objects.update_or_create(
# 查 封装了 name
name='太白2', # 查询参数
defaults = { #下面需要添加的值
'price':111,
'date':'2011-1-22'
}
) #太白22--111 True 没有的
print(obj1,obj2) # 水浒2-111 false 没创建
#如果查询的数据为多条 因为调用的是get方法 少了 不报错 异常捕获crate方法
#get() returned more than one Book -- it returned 7!
return HttpResponse('ok')
def query(request):
# exclude 排除,可以通过objects来调用,还可以通过queryset来调用
# obj_list = models.Book.objects.exclude(id=6)
# # 返回 queryset 可以调用.方法
# print(obj_list) #<QuerySet [<Book: 三国1--100>, <Book: 太白1--10>, <Book: 太白2--20>, <Book: 太白4--40>,
# #除了id=6的都提出来了
# obj_list1 = models.Book.objects.filter(price=100).exclude(id=4)
# print(obj_list1)
# 排序 # 管理器 按照price queryset类型
# obj_list2 = models.Book.objects.all().order_by('price') # 加个- -price (降序) id 加个相同的按照id排序
# print(obj_list2) # 默认升序
obj_list1 = models.Book.objects.all().order_by('-price').reverse() # 加个- -price (降序) id 加个相同的按照id排序
print(obj_list1)
obj_list2 = models.Book.objects.all().reverse()
print(obj_list2)
# 也可以按name排序,ascii首字母码 ,或者unicode中文
# 数
# obj_count = models.Book.objects.filter(price=100).count()
# print(obj_count) #8
# obj_list3 = models.Book.objects.filter(price=100)
# print(obj_list3.first()) #三国1--100
# print(obj_list3[0]) #三国1--100 model类型,没法.用法
# obj_list4 = models.Book.objects.filter(price=100)
# print(obj_list4.exists()) #True 用法:判断有没有数据,做什么事情
# 三种判断
# if obj_list4: # 把所有数据都取出来
# if obj_list4.exists(): 只判断一条数据 效率高 用这个
#if obj.list4.count() # 把所有数据都取出来也是
obj_list5 = models.Book.objects.filter(price=100).values('id','name')
# for obj in obj_list5:
# print(obj.id) # models对象 只能用属性
print(obj_list5) # 返回字典类型 所有的符合id name的
obj_list5 = models.Book.objects.filter(price=100).values_list('id','name') # 返回元祖
# 都是返回的queryset类型 上面的方法都可以用 所以这样
print(obj_list5,obj_list5[0],)
print(type(obj_list5[0])) #<class 'tuple'>
# values 和 value_list 都有 自动去重 distinct
obj_list6 = models.Book.objects.all().values('price').distinct() # 两个例子的情况都重复才算重复
print(obj_list6) #<QuerySet [{'price': 100}, {'price': 10}, {'price': 20}, {'price': 30}, {'price': 40}, {'price': 50}, {'price': 60}, {'price': 70}, {'price': 80}, {'price': 90}, {'price': 111}]>
aaa = models.Book.objects.filter(price__in=[11,22,33])
print(aaa) #<QuerySet []>
aaa = models.Book.objects.filter(price__gte=100) # >= gte > 100 gt
print(aaa)
# obj_list7 = models.Book.objects.filter(title_contains='太白')
# print(obj_list7)
# obj_list8 = models.Book.objects.filter(date__year='2019',date__day='04')
obj_list8 = models.Book.objects.filter(date__year='2019',date__day__gt='04')
# 双下滑线方法都可以连着用
print(obj_list8)
return HttpResponse('ok')
3
<1> all(): 查询所有结果,结果是queryset类型
<2> filter(**kwargs): 它包含了与所给筛选条件相匹配的对象,结果也是queryset类型 Book.objects.filter(title='linux',price=100) #里面的多个条件用逗号分开,并且这几个条件必须都成立,是and的关系,or关系的我们后面再学,直接在这里写是搞不定or的
<3> get(**kwargs): 返回与所给筛选条件相匹配的对象,不是queryset类型,是行记录对象,返回结果有且只有一个,
如果符合筛选条件的对象超过一个或者没有都会抛出错误。捕获异常try。 Book.objects.get(id=1)
两个错误类型:
<4> exclude(**kwargs): 排除的意思,它包含了与所给筛选条件不匹配的对象,没有不等于的操作昂,用这个exclude,返回值是queryset类型 Book.objects.exclude(id=6),返回id不等于6的所有的对象,或者在queryset基础上调用,Book.objects.all().exclude(id=6)
<5> order_by(*field): queryset类型的数据来调用,对查询结果排序,默认是按照id来升序排列的,返回值还是queryset类型
models.Book.objects.all().order_by('price','id') #直接写price,默认是按照price升序排列,按照字段降序排列,就写个负号就行了order_by('-price'),order_by('price','id')是多条件排序,按照price进行升序,price相同的数据,按照id进行升序
<6> reverse(): queryset类型的数据来调用,对查询结果反向排序,返回值还是queryset类型
<7> count(): queryset类型的数据来调用,返回数据库中匹配查询(QuerySet)的对象数量。
<8> first(): queryset类型的数据来调用,返回第一条记录 Book.objects.all()[0] = Book.objects.all().first(),得到的都是model对象,不是queryset
<9> last(): queryset类型的数据来调用,返回最后一条记录
<10> exists(): queryset类型的数据来调用,如果QuerySet包含数据,就返回True,否则返回False
空的queryset类型数据也有布尔值True和False,但是一般不用它来判断数据库里面是不是有数据,如果有大量的数据,你用它来判断,那么就需要查询出所有的数据,效率太差了,用count或者exits
例:all_books = models.Book.objects.all().exists() #翻译成的sql是SELECT (1) AS `a` FROM `app01_book` LIMIT 1,就是通过limit 1,取一条来看看是不是有数据
<11> values(*field): 用的比较多,queryset类型的数据来调用,返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列
model的实例化对象,而是一个可迭代的字典序列,只要是返回的queryset类型,就可以继续链式调用queryset类型的其他的查找方法,其他方法也是一样的。
不在是一个个model对象而是字典
<12> values_list(*field): 它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列
<13> distinct(): values和values_list得到的queryset类型的数据来调用,从返回结果中剔除重复纪录
2.9基于双下划线的模糊查询
Book.objects.filter(price__in=[100,200,300]) #price值等于这三个里面的任意一个的对象
Book.objects.filter(price__gt=100) #大于,大于等于是price__gte=100,别写price>100,这种参数不支持
Book.objects.filter(price__lt=100)
Book.objects.filter(price__range=[100,200]) #sql的between and,大于等于100,小于等于200
Book.objects.filter(title__contains="python") #title值中包含python的
Book.objects.filter(title__icontains="python") #不区分大小写
Book.objects.filter(title__startswith="py") #以什么开头,istartswith 不区分大小写
Book.objects.filter(pub_date__year=2012)
2.10 修改表记录
Book.objects.filter(title__startswith="py").update(price=120), update只能是querset类型才能调用,model对象不能直接调用更新方法,所以使用get方法获取对象的时候是不能update的。
此外,update()方法对于任何结果集(QuerySet)均有效,这意味着你可以同时更新多条记录update()方法会返回一个整型数值,表示受影响的记录条数。
注意:<input type="date" class="form-control" id="book_pub_date" placeholder="出版日期" name="book_pub_date" value="{{ edit_obj.pub_date|date:'Y-m-d' }}">,type='date'的input标签,value的值必须是'Y-m-d'的格式,这个标签才能认识并被赋值,所以,要通过date过滤给它改变格式。