Django模型

一、ORM映射转换:        

第一层意思:映射

Object                对象                --        models文件中定义的模型类对象

Relation                      关系                --        关系数据库中的数据表

Mapping             映射                --        对象和数据表的一一对应

实例对象                        --        一条完整数据记录

 

模型类                                数据库表

类名                                表名

属性                                字段

字段类型                        字段属性

 

第二层意思:转换

 

模型类做的一个动作                                具体的sql语句

all()                                                select* from …


在MVC框架中的Model模块中都包括ORM,对于开发人员主要带来了如下好处:

实现了数据模型与数据库的解耦,通过简单的配置就可以轻松更换数据库,而不需要修改代码

只需要面向对象编程,不需要面向数据库编写代码

在MVC中Model中定义的类,通过ORM与关系型数据库中的表对应,对象的属性体现对象间的关系,这种关系也被映射到数据表中,Django框架中ORM示意图如下

Django模型

 

二、自定义模型:

 

定义属性

  • 默认创建的主键列属性为id,可以使用pk代替,pk全拼为primary key
  • 属性命名限制
  • 不能是python的保留关键字
  • 不允许使用连续的下划线,这是由django的查询方式决定的定义属性时需要指定字段类型,通过字段类型的参数指定选项,语法如下:

属性=models.字段类型(选项)

 

 

字段类型

  • BooleanField:布尔字段,值为True或False
  • CharField(max_length=字符长度):字符串
  • 参数max_length表示最大字符个数
  • IntegerField:整数
  • DateField[auto_now=False, auto_now_add=False]):日期

 

选项

  • null:如果为True,表示允许为空,默认值是False
  • blank:如果为True,则该字段允许为空白,默认值是False
  • 对比:null是数据库范畴的概念,blank是表单验证证范畴的
  • default:默认值

 

关系字段类型

  • ForeignKey:一对多,将字段定义在多的一端中
  • ManyToManyField:多对多,将字段定义在两端中
  • OneToOneField:一对一,将字段定义在任意一端中

 

  • 由一到多的访问语法:

对象.模型类小写_set
例:bookinfo.heroinfo_set

  • 由一到一的访问语法

对象.模型类小写
例:heroinfo.bookinfo

  • 访问关联对象的id语法

对象.属性_id
例:heroinfo.book_id

 

元选项

  • 数据表的默认名称为

<app_name>_<model_name>
例:booktest_bookinfo

  • 在模型类中定义类Meta,用于设置元信息,如使用db_table自定义表的名字

 

三、模型成员

 

模型实例方法

  • str:在将对象转换成字符串时会被调用
  • save():将模型对象保存到数据表中
  • delete():将模型对象从数据表中删除

 

 

管理器:

默认管理器:

默认的名称是objects

可以改名,以覆盖的形式:books= models.Manager()

注意:二者只能生存一个

 

自定义的管理器: books = BookInfoManager()

1、修改原始查询集,重写get_queryset()方法,更改(重写)某个特殊类型属性

2、向管理器类中添加额外的方法,如创建对象,增加一个特殊的属性

注意:自定义的管理器可以和默认管理器同时存在

 

 

四、查询集

 

  • 两大特性
  • 惰性执行:创建查询集不会访问数据库,直到调用数据时,才会访问数据库,调用数据的情况包括迭代、序列化、与if合用
  • 缓存:查询集的结果被存下来之后,再次查询时会使用之前缓存的数据

 

返回列表的过滤器如下:

  • all():返回所有数据
  • filter():返回满足条件的数据
  • exclude():返回满足条件之外的数据,相当于sql语句中where部分的not关键字
  • order_by():排序

 

返回单个值的过滤器如下:

  • get():返回单个满足条件的对象
  • count():返回当前查询的总条数
  • aggregate():聚合
  • exists():判断查询集中是否有数据

 

限制查询集

  • 查询集返回列表,可以使用下标的方式进行限制
  • 示例:list=BookInfo.books.all()[0:2]

 

 

字段查询

  • 语法如下:
  • 说明:属性名称和比较运算符间使用两个下划线,所以属性名不能包括多个下划线,属性名称__比较运算符=

 

条件运算符

  • exact:表示判等
  • contains:是否包含
  • startswith、endswith:以指定值开头或结尾
  • isnull:是否为null
  • 以上运算符都区分大小写,在这些运算符前加上i表示不区分大小写,如iexact、icontains、istartswith、iendswith
  • in:是否包含在范围内
  • gt、gte、lt、lte:大于、大于等于、小于、小于等于
  • 不等于使用等于的运算符,使用exclude()过滤器
  • year、month、day、week_day、hour、minute、second:对日期时间类型的属性进行运算

 

关联查询

  • 语法如下:

关联模型类名小写__属性名__运算符=

  • 如果没有没有“__运算符”部分,表示等于,结果和sql中的inner join相同
  • 例:查询图书,要求图书中英雄的描述包含‘八’

list =BookInfo.books.filter(heroinfo__hcontent__contains='')

 

  • 例:查询书名为“天龙八部”的所有英雄

list =HeroInfo.objects.filter(hbook__btitle='天龙八部')

 

F对象

  • 之前的查询都是对象的属性与常量值比较,两个属性怎么比较呢? 答:使用F对象,被定义在django.db.models中
  • 语法如下:F(属性名)
  • 例:查询阅读量大于等于评论量的图书

from django.db.models importF
...
list = BookInfo.books.filter(bread__gte=F('bcommet'))

 

  • 可以在F()对象上使用算数运算
  • 例:查询阅读量大于2倍评论量的图书

list =BookInfo.books.filter(bread__gt=F('bcommet') * 2)

 

 

Q对象

  • 多个过滤器逐个调用表示逻辑与关系,同sql语句中where部分的and关键字
  • 例:查询阅读量大于20,并且编号小于3的图书

list=BookInfo.books.filter(bread__gt=20,id__lt=3)

list=BookInfo.books.filter(bread__gt=20).filter(id__lt=3)

 

  • 如果需要实现逻辑或or的查询,需要使用Q()对象结合|运算符
  • Q对象被义在django.db.models中
  • 语法如下:Q(属性名__运算符=)
  • 例:查询阅读量大于20的图书,改写为Q对象如下

from django.db.models importQ
...
list = BookInfo.books.filter(Q(bread__gt=20))

 

  • Q对象可以使用&、|连接,&表示逻辑与,|表示逻辑或
  • 例:查询阅读量大于20,或编号小于3的图书,只能使用Q对象实现

list =BookInfo.books.filter(Q(bread__gt=20) | Q(pk__lt=3))

 

 

  • Q对象前可以使用~操作符,表示非not
  • 例:查询编号不等于3的图书

list =BookInfo.books.filter(~Q(pk=3))

 

 

聚合函数

  • 使用aggregate()过滤器调用聚合函数
  • 聚合函数包括:Avg,Count,Max,Min,Sum,被定义在django.db.models中
  • 例:查询图书的总阅读量

from django.db.models importSum
...
list = BookInfo.books.aggregate(Sum('bread'))

 

  • 使用count时一般不使用aggregate()过滤器
  • 例:查询图书总数

list = BookInfo.books.count()