model类的属性参数
比如:models.CharField(null=True,blank=True)
(1)null
如果为True,Django将用NULL在数据库中存储空值。默认值时False
(2)blank
如果为True,该字段允许不填。默认为False。
要注意,这与null不同。null纯粹是数据库范畴的,而blank是数据验证范畴
如果一个字段的blank=True,表单的验证将允许该字段是空值。如果字段的blank=False,该字段就是必填的。
(3)default
字段的默认值。可以是一个值或者可调用对象。如果可调用,每有新对象被创建它都会被调用,如果你的字段没有设置可以为空,那么将来如果我们后添加一个字段,这个字段就要给一个default值。
(4)primary_key
如果为True,那么这个字段就是模型的主键。如果你没有指定任何一个字段的primary_key=True,Django就会自动添加一个IntegerField字段作为主键,所以除非你想要覆盖默认的主键行为,否则没必要设置任何一个字段的primary_key=True.
(5)unique
如果该值设置为True,这个数据字段的值在整张表中必须是唯一的。
(6)choices
由二元组组成的一个可迭代对象(例如,列表或元组),用来给字段提供选择项。如果设置了choices,默认的表单将是一个选择框而不是标准的文本框,<br>而且这个选择框的选项就是choices中的选项。
(7)db_index
如果db_index=True则代表着为此字段设置数据库索引。普通索引
DatetimeField/DateField/TimeField这个三个时间字段,都可以设置如下属性
(8)auto_now_add
配置auto_now_add=True,创建数据记录的时候会把当前时间添加到数据库
(9)auto_now
配置上auto_now=True,每次更新数据记录的时候会更新该字段,标识这条记录最后一次的修改时间。
只能在save方式时触发自动更新时间的动作。
models中的Field类对应类型和对应的mysql的数据类型对比
可以在pip安装的django包中的这个位置差
/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/db/backends/mysql/base.py
完整的类型字段大全
'AutoField': 'integer AUTO_INCREMENT',
'BigAutoField': 'bigint AUTO_INCREMENT',
'BinaryField': 'longblob',
'BooleanField': 'bool',
'CharField': 'varchar(%(max_length)s)',
'CommaSeparatedIntegerField': 'varchar(%(max_length)s)',
'DateField': 'date',
'DateTimeField': 'datetime',
'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)',
'DurationField': 'bigint',
'FileField': 'varchar(%(max_length)s)',
'FilePathField': 'varchar(%(max_length)s)',
'FloatField': 'double precision',
'IntegerField': 'integer',
'BigIntegerField': 'bigint',
'IPAddressField': 'char(15)',
'GenericIPAddressField': 'char(39)',
'NullBooleanField': 'bool',
'OneToOneField': 'integer',
'PositiveIntegerField': 'integer UNSIGNED',
'PositiveSmallIntegerField': 'smallint UNSIGNED',
'SlugField': 'varchar(%(max_length)s)',
'SmallIntegerField': 'smallint',
'TextField': 'longtext',
'TimeField': 'time',
'UUIDField': 'char(32)',
ORM数据库增删改查动作
增加
def add_book(request):
import datetime
#添加数据
#方式1
book_obj = models.Book(
title = '少年阿宾',
state = True,
#日期时间类型数据,通过字符串或者日期时间类型数据作为参数数据,都是可以的。
pub_date = datetime.datetime.now(),
#pub_date = '2020-7-16',
price = 11.11,
publish = '三星出版社'
)
print(book_obj.title)
print(book_obj.publish)
book_obj.save() #保存数据
#方式2
book_obj = models.Book.objects.create(
title = '蜡笔小新',
state=True,
pub_date=datetime.datetime.now(),
#pub_date='2020-7-16',
price=1.5,
publish='小新出版社'
)
#重点记录:create方法会返回新添加的这条记录的类对象,通过这个类对象.属性的方式能够获取到对应字段的数据
print(book_obj) #Book object
print(book_obj.title) #蜡笔小新
return HttpResponse('OK')
批量添加数据
看示例:bulk_create
obj_list = []
for i in range(1,10):
obj = models.Book(
title=f'水浒传{i}',
state = True,
pub_date=f'2020-7-{i}',
price=11.11+i,
publish='腾讯出版社'
)
obj_list.append(obj)
models.Book.objects.bulk_create(obj_list)
更新或添加
Update_or_create()
#有就更新,没有就添加update_or_create()
#有就更新的操作示例:
models.Book.objects.update_or_create(
id=6,
default={
'title':'三国志',
'state':True,
'pub_date':'2018-11-11',
'price':20.22,
'publish':'三国出版社'
}
)
#没有就创建(添加)的示例:
models.Book.objects.update_or_create(
id=100,
default={
'title':'红梦楼',
'state':True,
'pub_date':'2020-6-6',
'price':22.34,
'publish':'红楼梦出版社'
}
)
#上述update_or_create查询的只能是单条数据,不能多条!!
#查询为多条记录的演示:报错,因为update_or_create内部进行查询时,使用的是get方法查询
models.Book.object.update_or_create(
publish='腾讯出版社',
defaults={
'title':'红楼梦2',
'state':True,
'pub_date':'2020-2-6',
'price':2.4,
'publish':'红楼梦出版社'
}
)
查询或添加
get_or_create()
#查询或创建,能够查询到就返回查询结果,查询不到就添加记录,查询时内部使用的还是get方法,所以只针对一条,多条就会报错
ret = models.Book.objects.get_or_create(
id=100,
default={
'title':'十万个为什么',
'state':True,
'pub_date':'2020-5-6',
'price':33.4,
'publish':'为什么出版社'
}
)
print(ret) #(<Book: 十万个为什么>, False)#查到记录,第二个参数为没有创建所以返回False。
#查询不到,自动添加记录的示例
ret = models.Book.objects.get_or_create(
id=102,
default={
'title':'三毛历险记',
'state':True,
'pub_date':'2020-4-5',
'price':23.44,
'publish':'三毛出版社'
}
)
print(ret)#(<Book: 三毛历险记>, True)#第二个参数为创建了新记录,所以返回True.
查询
几个简单查询方法
all()查询所有的数据,返回结果为QuerySet类型数据,QuerySet类似于列表,里面存放的是model类的实例化对象,每个对象表示一条记录,对象中的对应数据有着该行记录的字段数据
obj_list = models.Book.objects.all()
#QuerySet类似于列表,但是比列表还多一些其他的功能,这是orm给咱们封装出来的新的数据类型
#<QuerySet [<Book: 蜡笔小新>, <Book: 西游记>]>
print(obj_list) #<QuerySet [<Book: 蜡笔小新>, <Book: 西游记>,...]>
print(obj_list[0]) #索引取值 取的是对象
print(obj_list[0:3]) #切片 里面存放的都是对象,所以取出来的都是一个个对象
filter() 过滤数据,结果也是QuerySet类型数据,里面的每一项也是模型类对象
obj_list = models.Book.objects.filter(id=1)
print(obj_list) #查询一个就返回一个<QuerySet [<Book: 蜡笔小新>]>
obj_list = models.Book.objects.filter(publish='腾讯出版社')
print(obj_list)#查询多个就返回<QuerySet [<Book: 水浒传1>, <Book: 水浒传2>..]>
#当查不到任何内容时,返回空的queryset,不会报错
obj_list = models.Book.objects.filter(id=400)
print(obj_list) #<QuerySet []>
过滤数据,但是结果有且只能有一条,结果不是queryset类型数据,而是一个模型类对象
obj = models.Book.objects.get(id=1)
print(obj) #模型类对象
print(obj.price) #11.11
print(obj.publish) #腾讯出版社
错误示例:当成查询结果为多个时,就会报错
obj = modles.Book.objects.get(publish='腾讯出版社')
print(obj)
#查询结果不止一个,多于一个,就报这个错
#get() returned more than one Book -- it returned 9!
错误示例:当查不到任何数据时,也会报错
obj= models.Book.objects.get(id=101)
print(obj)
#Book mathching query dose not exist.
修改
方式1 模型类对象修改数据
obj = models.Book.objects.get(id=1)#get查询出来的结果是模型类对象
obj.title='少年小白' #直接对象.属性=新值 就是修改
obj.price=20
obj.save()
方式2update方法,调用者是objects控制器,可以是queryset类型数据,但是不能是模型类对象
objects调用,下面示例是整列数据更新
models.Book.objects.update(
state=False,
title='xx',
)
queryset类型数据调用,下面也是更新整列数据
models.Book.objects.all().update(
state=True
)
queryset类型调用数据,更新部分记录数据
obj = models.Book.objects.filter(id=101).update(
title='三毛当兵记'
)
print(obj) #1 返回的是受影响的行数
模型对象调用update方法,报错示例:
models.Book.objects.get(id=1).update(
title='xx'
)
报错信息:'Book' object has no attribute 'update'
删除
删除delete方法,调用者可以是model对象,可以是quertset类型数据,不可以是 objects控制器
#模型类对象示例:
obj = models.Book.objects.get(id=101).delete()
print(obj) #(1,{'app01.Book': 1}) 返回元组,参数是受影响行数
#queryset类型示例:
obj =models.Book.objects.filter(publish='吴承恩出版社').delete()
print(obj) #(2,{'app01.Book': 2}) 返回受影响的行数
#objects控制器 报错示例:
obj= models.Book.objects.delete()
print(obj) #报错,objects控制器不能调用delete方法
如果想删除所有数据,需要自己指明数据写法如下:
obj = models.Book.object.all().delete()
print(obj)
查询的13个API接口
查询所有结果,结果为queryset类型
models.Book.objects.all()
它包含了所给筛选条件相匹配的对象,结果也是queryset类型,可以被queryset类型数据调用,也可以直接通过objects控制器进行调用
models.Book.objects.filter(id=5) #filter(id!=5)不能直接写不等于,想做不等于排除查询使用下面的exclude方法
models.Book.objects.all().filter(id=5)
models.Book.objects.filter(title='linux',price=100)#里面的多个条件用逗号分开,并且这几个条件必须都成立,是and关系
也可以这样写
models.Book.objects.filter(**{'title':'linux','price':100})#字典解包
返回与所给筛选条件匹配的对象,结果不是queryset类型,是行记录(模型类对象)对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误,捕获异常try,get方法调用者可以是quertset类型数据,也可以是objects控制器
示例:
models.Book.objects.get(id=1)
models.Book.objects.all().get(id=8)
排除的意思,它包含了与给筛选条件不匹配的对象,没有不等于的操作,用这个exclude,返回值是queryset类型,调用者可以是queryset类型数据,也可以是objects控制器
示例:
models.Book.objects.exclude(id=6)#返回id不等于6的所有对象
models.Book.objects.all().exclude(id=6)
对查询结果排序,返回值还是queryset类型,调用者可以是queryset类型数据,也可以是objects控制器
示例:
models.Book.objects.order_by('price')#获取所有数据,并且按照price字段升序排列
models.Book.objects.order_by('-price')##获取所有数据,并且按照price字段降序排列
models.Book.objects.all().order_by('price')#queryset类型数据调用
多条排序示例:
models.Book.objects.all().order_by('price','id')#先按照price进行升序,得到的结果再按照id进行升序
可以是queryset类型的数据来调用,也可以是objects控制器调用,对结果反向排序,返回值还是queryset类型
示例:
obj_list = models.Book.objects.all().order_by('id').reverse()
obj_list = models.Book.objects.reverse()#注意,如果没给Book模型类执行Meta中的ordering属性,那么reverse()默认是不生效的。需要在models.py文件中红定义一个Meta类
class Meta:
ordering=['id',]
queryset类型的数据来调用,也可以是objects控制器,返回数据库中匹配查询(QuerySet)的对象数量.返回结果是个数字。
obj_list = models.Book.objects.count() #默认统计的整表的所有数据量
obj_list = models.Book.objects.all().count()
queryset类型的数据来调用,也可以是objects控制器调用,返回第一条记录对象,结果得到的都是model对象,不是queryset
示例:
models.Book.objects.all().first() #同Book.objects.all()[0]
models.Book.objects.first()
quertset类型的数据来调用,也可以是objects控制器调用,返回最后一条记录对象,结果得到的都是model对象,不是queryset
示例
models.Book.objects.all().last()#注意不能用models.Book.objects.all()[-1],不支持负数索引下标取值,会报错
models.Book.objects.last()
queryset类型的数据来调用,也可以是objects控制调用,如果queryset包含数据就返回True,否则返回False
示例:
obj_list = models.Book.objects.exists() #判断整表是否有数据
obj_list = models.Book.objects.filter(id=100).exists() #判断查询结果集中是否有数据,有得到True,没有得到False
还有个点需要注意一下:
空的queryset类型数据布尔值为False,但是一般不用它来判断数据库里面是不是有数据,如果有大量的数据,你用它来判断,那么就需要查询出所有的数据,效率太差了,用count或者exists
示例:
select * from book where name='xx';
if obj_list: 会将满足条件的所有数据进行一次查询,效率低
select count(id) from book where name='xx';
if obj_list.count():效率较高,按照查询对象的id值进行个数统计
select id from book where name='xx' limit 1;查询一条数据
if obj_list.exists(): #效率高
例子:
all_books = models.Book.objects.all().exists()#翻译成sql是select (1) as a from app01_app limit 1;
用的比较多,queryset类型的数据来调用,也可以是objects调用,返回一个特殊的QuertSet,运行后得到的并不是一系列model的实例化对象,返回的queryset类型,里面的元素是字典数据,既然是queryset类型数据,那么就可以继续链式调用queryset类型的其他查找方法,其他方法也是一样的
示例:
obj_list = models.Book.objects.values() #默认获取的表中所有记录的字典数据,字典中的字段名称(模型类属性名称),值是每个字段的对应数据
obj_list = models.Book.objects.all().values()
#取指定字段数据
obj_list = models.Book.objects.all().values('id','title')
#<QuerySet [{'id': 5, 'title': '水浒传2'}, {'id': 6, 'title': '西游记'},...]>
它与values()非常相似,它返回的是一个包含元组queryset序列,values返回的是一个包含字典的queryset序列
示例:
obj_list = models.Book.objects.all().values_list('id','title')
#结果:#<QuerySet [(5, '水浒传2'), (6, '西游记'),...]>
#不太好的一点,就是数据补知道对应的是哪个字典
去重,values和values_list得到的queryset类型的数据来调用,从返回结果中剔除重要重复记录
示例:
obj_list = models.Book.objects.distinct()
models.Book.objects.all().distinct()和models.Book.objects.distinct()都是按照整条记录数据是否重复来进行去重,所以没有效果,因为最起码id数据是主键,不能重复,索引distinct方法不适合用在查询结果集中元素为模型类对象的这种结果集来去重
所以一般都是用在values和values_list方法后面,因为他们两个可以获取出指定字段数据,然后再去重
obj_list = models.Book.objects.all().values('publish').distinct()
print(obj_list)
传参的两种方式
方式1
filter(id=5, publish='腾讯出版社')
create(id=5, publish='腾讯出版社')
方式2
filter(**{'id':5, 'publish':'腾讯出版社'})
关于排序 reverse()
方式1:
order_by(*field)方法进行排序
方式: 在模型类中通过Meta类来执行排序规则
class Book(models.Model):
id = models.AutoField(primary_key=True) #自增、主键
title = models.CharField(max_length=64,null=True) #
state = models.BooleanField(default=True)
pub_date = models.DateField(null=True)
# price = models.DecimalField(max_digits=20,decimal_places=5,null=True)
price = models.DecimalField(max_digits=8,decimal_places=2,null=True)
publish = models.CharField(max_length=32)
def __str__(self):
return self.title + '价格' + str(self.price)
class Meta:
ordering = ['id',] #制定了它之后,所有的本表的查询结果,都按照id进行升序排列,还可进行多天剑排序规则的指定
reverse()翻转,必须在上面两者的基础上,才能进行结果顺序翻转