创建ORM模型
1.orm模型一般都是放在app的models.py文件中。每个app都可以拥有自己的模型。并且,如果这个模板想要映射到数据库中,那么这个app必须要放在settings,py 的 INSTALLED_APP中进行安装。
2.这个模型类继承自django.db.modles.Model.不然不能映射到数据库中。这个模型类以后映射到数据库中,表名是app名字小写_类名的小写。字段名是类中定义的属性名。
3.属性的数据类型映射到表的每个字段的约束类型。是models下的各种filed的实例对象(AutoFileld,CharFileld,DatetimeField)
4.执行命令 : python manage.py makemigirations 生成迁移脚本文件。
5 同样执行命令: python manage.py migrate 将迁移脚本文件映射到数据库中
通过操作orm模型类来执行数据库的增删改查操作、
1. model类的属性参数
比如:models.CharField(null=True,blank=True) (1)null 如果为True,Django 将用NULL 来在数据库中存储空值。 默认值是 False. (1)blank 如果为True,该字段允许不填。默认为False。 要注意,这与 null 不同。null纯粹是数据库范畴的,而 blank 是数据验证范畴的。 如果一个字段的blank=True,表单的验证将允许该字段是空值。如果字段的blank=False,该字段就是必填的。 (2)default 字段的默认值。可以是一个值或者可调用对象。如果可调用 ,每有新对象被创建它都会被调用,如果你的字段没有设置可以为空,那么将来如果我们后添加一个字段,这个字段就要给一个default值 (3)primary_key 如果为True,那么这个字段就是模型的主键。如果你没有指定任何一个字段的primary_key=True, Django 就会自动添加一个IntegerField字段做为主键,所以除非你想覆盖默认的主键行为, 否则没必要设置任何一个字段的primary_key=True。 (4)unique 如果该值设置为 True, 这个数据字段的值在整张表中必须是唯一的 (5)choices 由二元组组成的一个可迭代对象(例如,列表或元组),用来给字段提供选择项。 如果设置了choices ,默认的表单将是一个选择框而不是标准的文本框,<br>而且这个选择框的选项就是choices 中的选项。 (6)db_index 如果db_index=True 则代表着为此字段设置数据库索引。 DatetimeField、DateField、TimeField这三个时间字段,都可以设置如下属性。 (7)auto_now_add 配置auto_now_add=True,创建数据记录的时候会把当前时间添加到数据库。 (8)auto_now 配置上auto_now=True,每次更新数据记录的时候会更新该字段,标识这条记录最后一次的修改时间。 只能在save方式时触发自动更新时间的动作
ORM数据库增删改查动作
from django.shortcuts import render,HttpResponse
from app01 import models
def add_book(request):
import datetime
# 添加数据
# 方式一
book_obj = models.Mybook(
title='看不见的光',
state=True,
pub_date='2010-03-04',
price=45.5,
publish='人民出版社'
)
print(book_obj.title)
print(book_obj.price)
book_obj.save() # 这是保存数据
return HttpResponse('已添加')
# 方式二:
book_obj = models.Mybook.objects.create(
title='激荡十年',
state=True,
# 日期时间类型数据,通过字符串或者日期时间类型数据作为参数数据,都是可以的
pub_date=datetime.datetime.now(),
price=39.9,
publish='北京出版社'
)
print(book_obj)
print(book_obj.title)
print(book_obj.price)
# 重点记录:create方法会返回新添加的这条记录的类对象,通过这个对象.属性的方式能够获取到对应字段的数据
return HttpResponse('操作成功')
批量添加数据: 使用bulk_create
from django.shortcuts import render,HttpResponse
from app01 import models
def add_book(request):
obj_list = []
for i in range(1,10):
obj = models.Mybook(
title=f'大国的博弈{i}',
state=True,
pub_date=f'2018-07-{i}',
price=35+i,
publish='云出版社'
)
obj_list.append(obj)
models.Mybook.objects.bulk_create((obj_list))
return HttpResponse('已批量添加')
更新或添加: Update_or_create()
# 有就更新的操作
models.Mybook.objects.update_or_create(
id=5,
defaults={
'title':'边城',
'state':True,
'pub_date':'2018-07-05',
'price':29.9,
'publish':'人民出版社'
}
)
# 没有就创建的案例
models.Mybook.objects.update_or_create(
id=20,
defaults={
'title': '边城',
'state': True,
'pub_date': '2018-07-05',
'price': 29.9,
'publish': '人民出版社'
}
)
# 查询为多条记录: 报错,因为update_or_create内部进行查询时用的get方法
# get() returned more than one Mybook -- it returned 8!
models.Mybook.objects.update_or_create(
publish='人民出版社',
defaults={
'title': '三三',
'state': True,
'pub_date': '2018-07-05',
'price': 29.9,
'publish': '人民出版社'
}
)
return HttpResponse('ok')
查询或添加: get_or_create()
ret = models.Mybook.objects.get_or_create(
id=15,
defaults={
'title': '三三',
'state': True,
'pub_date': '2018-07-05',
'price': 29.9,
'publish': '人民出版社'
}
)
print(ret) # (<Mybook: 大国的博弈7>, False) id为15是有数据的, 所以直接返回数据了, 没有创建, 返回结果元祖中第二个值为False
# 没数据创建数据
ret = models.Mybook.objects.get_or_create(
id=50,
defaults={
'title': '三三',
'state': True,
'pub_date': '2018-07-05',
'price': 29.9,
'publish': '人民出版社'
}
)
print(ret) # (<Mybook: 三三>, True) id为50是没有数据的, 所以创建数据了, 返回结果元祖中第二个值为True
return HttpResponse('ok')
(2) 几种查询方法
all()查询所有的数据,返回结果为QuerySet类型数据,QuerySet类似于列表,里面存放的是model类的实例化对象,每个对象表示一条记录,对象中的对应数据有着该行记录的字段数据
def get_book(request):
obj_list = models.Mybook.objects.all()
print(obj_list[0]) # 索引取值
print(obj_list[1:4]) # 切片取值
return HttpResponse('OK')
# QuerySet类似于列表,但是比列表还多一些其他的功能,这是orm封装出来的新的数据类型
# <QuerySet [<Mybook: 看不见的光>, <Mybook: 看不见的光>, <Mybook: 看不见的光>]>
filter() 过滤查询 ,结果也是queryset类型数据,里面的每一项也是模型类对象, 查找不到内容时, 返回空的查询结果集
obj_list = models.Mybook.objects.filter(id=9)
print(obj_list) # <QuerySet [<Mybook: 大国的博弈1>]>
obj_list = models.Mybook.objects.filter(publish='北京出版社')
print(obj_list) # <QuerySet [<Mybook: 看不见的光>, <Mybook: 激荡十年>]> 查找内容可以是多项
get() 过滤查询,但是结果有且只能有一条,结果不是queryset类型数据,而是一个模型类对象
obj = models.Mybook.objects.get(id=5)
print(obj) # Mybook object
print(obj.price) # 29.90000
# 当查询结果有多项时, 报错
obj = models.Mybook.objects.get(publish='北京出版社')
print(obj)
# get() returned more than one Mybook -- it returned 2!
# 当查询不到数据时 也会报错
obj = models.Mybook.objects.get(id=80)
print(obj)
# Mybook matching query does not exist.
修改
def update_book(request):
# 方式一: 模型类对象修改数据
obj = models.Mybook.objects.get(id=5)
obj.title = '我的前半生'
obj.price = 49
obj.save()
# 方式二: update方法, 调用者可以是objects控制器, 也可以是queryset类型数据, 但是不能是模型类对象
# (1) objects调用, 整列更新
models.Mybook.objects.update(
state = False
)
# (2) queryset调用, 整列更新
models.Mybook.objects.all().update(
state = True
)
# (3) queryset类型数据调用, 更新部分数据
obj = models.Mybook.objects.filter(publish='云出版社').update(
price = 19.9
)
print(obj) # 9 返回受影响的行数
# 模型类数据调用update方法的错误演示如下
models.Mybook.objects.get(id=7).update(
price = 66
)
# 'Mybook' object has no attribute 'update'
删除: delete
def del_book(request):
# 调用者可以是model对象, 也可以是queryset对象
obj = models.Mybook.objects.get(id=5).delete()
print(obj) # (1, {'app01.Mybook': 1}) 返回结果是受影响的行数
obj = models.Mybook.objects.filter(publish='人民出版社').delete()
print(obj) # (7, {'app01.Mybook': 7})
# 错误演示:
obj = models.Mybook.objects.delete()
# 'Manager' object has no attribute 'delete'
# 控制器没有delete方法,原因就是怕一下子删除了所有数据
# obj = models.Mybook.objects.all().delete()
# 这个是删除所有数据
return HttpResponse('OK')
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的关系,or关系的在这里写是搞不定的
(3) get(**kwargs): 返回与所给筛选条件相匹配的对象,结果不是queryset类型,是行记录(模型类对象)对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。用的时候最好带上捕获异常try, get方法调用者可以是queryset类型数据,也可以是objects控制器。
models.Book.objects.get(id=1) models.Book.objects.all().get(id=8)
(4) exclude(**kwargs): 排除的意思,它包含了与所给筛选条件不匹配的对象,没有不等于的操作昂,用这个exclude,返回值是queryset类型 ,调用者可以是queryset类型数据,也可以是objects控制器。
obj = models.Mybook.objects.exclude(id=4)
print(obj)
(5) order_by(*field): 对查询结果排序, 返回值还是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,默认是按照price升序排列,按照字段降序排列,就写个负号就行了order_by('-price'),order_by('price','id')是多条件排序,按照price进行升序,price相同的数据,按照id进行升序
(6) reverse(): 可以是queryset类型的数据来调用,也可以是objects控制器调用,对查询结果反向排序,返回值还是queryset类型
方式1: order_by(*field)方法进行排序
obj_list = models.Book.objects.all().order_by('id').reverse() 方式2: 在模型类中通过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进行升序排列,还可进行多条件排序规则的指定
obj_list = models.Book.objects.reverse()
reverse()翻转,必须在上面两者的基础上,才能进行结果顺序翻转
(7) count(): queryset类型的数据来调用,也可以是objects控制器调用,返回数据库中匹配查询(QuerySet)的对象数量。返回结果是个数字。
obj_list = models.Book.objects.count() #默认统计的整表的所有数据量 obj_list = models.Book.objects.all().count()
(8) first(): queryset类型的数据来调用,也可以是objects控制器调用,返回第一条记录对象,结果得到的都是model对象,不是queryset
Book.objects.all().first() #同:Book.objects.all()[0] Book.objects.first()
(9) last(): queryset类型的数据来调用,也可以是objects控制器调用,返回最后一条记录对象,结果得到的都是model对象,不是queryset
Book.objects.all().last()
#同:Book.objects.all()[-1] ,但是负数索引取值会报错,错误信息为: Negative indexing is not supported. queryset类型数据,不支持负数索引取值的形式 Book.objects.last()
(10) exists(): 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_book` LIMIT 1,就是通过limit 1,取一条来看看是不是有数据
(11) values(*field): 用的比较多,queryset类型的数据来调用,也可以是objects调用,返回一个特殊的QuerySet,运行后得到的并不是一系列model的实例化对象,返回的queryset类型,里面的元素是字典数据,既然是queryset类型数据,那么就可以继续链式调用queryset类型的其他的查找方法,其他方法也是一样的。
# obj_list = models.Book.objects.values() #默认获取的表中所有记录的字典数据,字典中的键是字段名称(模型类属性名称),值是每个字段的对应数据
# obj_list = models.Book.objects.all().values()
# 取指定字段数据
obj_list = models.Mybook.objects.all().values('id','title')
print(obj_list)
# <QuerySet [{'id': 7, 'title': '看不见的光'}, {'id': 8, 'title': '激荡十年'},{...}
(12) values_list(*field): 它与values()非常相似,它返回的是一个包含元组queryset序列,values返回的是一个包含字典queryset序列
obj_list = models.Mybook.objects.all().values_list('id','title')
print(obj_list)
# <QuerySet [(7, '看不见的光'), (8, '激荡十年'),(...)]
(13) distinct(): 去重, values和values_list得到的queryset类型的数据来调用,从返回结果中剔除重复纪录
class Book(models.Model):
id = models.AutoField(primary_key=True) #自增、主键
...
publish = models.CharField(max_length=32)
def __str__(self):
return self.title + '价格' + str(self.price)
class Meta:
ordering = ['id','publish',]
obj_list = models.Book.objects.all().order_by('publish').values('publish').distinct()
#当模型类中指定了默认排序字段,那么当我们使用distinct方法进行去重时,默认会按照我们指定的排序字典进行去重,会导致去重结果不是我们想要的,
所以要么我们在模型类中不指定排序字段,如果指定了排序字段,我们在使用distinct方法前面加上order_by方法,并且order_by方法中的字段就是我们要去重的字段数据
官方文档中的下面这种写法
Entry.objects.order_by('pub_date').distinct('pub_date')
只适用于PostgreSQL数据库,mysql不支持distinct方法里面写字段
(14)
class Book(models.Model):
...
# sex = models.CharField(max_length=12)
sex_choices = ((1, '男性'),(0, '女性')) #enum枚举 单选
sex = models.IntegerField(choices=sex_choices, default=1)
获取含有choices属性的字典数据方法
ret = models.Book.objects.get(id=5)
print(ret.sex) # 1 获取到的是数据库中存储的字段数据
print(ret.get_sex_display()) # 男性 -- 能够帮我们获取到该字段数据对应的choices指定的元祖中的这个数据对应的文本内容
# sex_choices = ((1, '男性'), (0, '女性')) # enum枚举 单选
# sex = models.IntegerField(choices=sex_choices, default=1)
# 比如拿sex这个字段来说,数据库中存的数据是1,表示男性,如果我想获取到男性这个字符串数据,直接通过模型类对象.get_sex_display()这个方法就能获取到,
这个方法的语法是get_模型类属性名称_display()
(15)
class ShowTime(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=32)
brithday = models.DateTimeField(auto_now_add=True) #添加记录时,自动添加创建时间
bday = models.DateTimeField(auto_now=True) #添加记录时,也能自动添加创建时间,并且更新记录时,自动更新为当前时间
#models.DateTimeField(auto_now=True)中的auto_now=True对update方法没有效果
# models.ShowTime.objects.all().update(
# name='chao2',
# )
#auto_now=True只有在使用save方法来进行更新动作时,才生效,才会自动更新修改时间
ret = models.ShowTime.objects.get(id=1)
ret.name = 'zhen'
ret.save()
关键字传参
两种方式:
方式1
filter(id=5, publish='腾讯出版社')
create(id=5, publish='腾讯出版社')
...
方式2
filter(**{'id':5, 'publish':'腾讯出版社'})
...
基于双下划线的模糊查询
# 值等于一个范围里的任意一个的对象 models.Book.objects.filter(price__in=["11.9","99"]) # 针对decimal写字符串的形式 models.Book.objects.filter(price2__in=[20, 18]) # 针对float或者int类型用数字 # 大于查询: gt models.Book.objects.filter(price__gt=11.9) # 大于等于查询: gte models.Book.objects.filter(price__gte=11) 小于查询: lt models.Book.objects.filter(price__lt=11.9) 小于等于查询: lte models.Book.objects.filter(price__lte=11.9) 范围查询: range models.Book.objects.filter(price__range=["11.9","15.9"]) # 相当于sql的between and,大于等于100,小于等于200, 查询是小数的话要写成字符串
针对字符串的操作:
# 包含某些字符串的操作: contains models.Book.objects.filter(title__contains="的") Book.objects.filter(title__icontains="python") # 前面加i表明不区分大小写 # 找到以某些字符串开头或者结尾的 models.Book.objects.filter(title__startswith="看") Book.objects.filter(title__istartswith='p') # 前面加i表明不区分大小写 Book.objects.filter(title__endswith="py") # 以什么结尾 Book.objects.filter(title__iendswith='p') # iendswith 不区分大小写
日期类型的数据操作
# 以年份查找 models.Book.objects.filter(pub_date__year=2019) # 以年月查找 models.Book.objects.filter(pub_date__year=2019,pub_date__month=7) # 以月查找 models.Book.objects.filter(pub_date__month=7) # 查询某个字段为空的数据 models.Book.objects.filter(title__isnull=True) #正规的 models.Book.objects.filter(title=None)
查看某个orm语句的原生sql语句方法
print(models.Book.objects.filter(title__isnull=True).query)


浙公网安备 33010602011771号