django-模型

一、ORM简介

在MVC框架中包括一个重要的部分,就是ORM,它实现了数据模型与数据库的解耦,及数据模型的设计不需要依赖于特定的数据库,通过简单的配置就可以轻松的更换数据库。

ORM是“对象-关系-映射”的简称,主要任务是:

    1.)根据对象的类型生成表结构
    2.)将对象、列表的操作,转换为sql语句
    3.)将sql查询的结构转换成对象、列表

Django中的模型包含存储数据的字段和约束,对应着数据库中唯一的表

二、数据库 MySQL

这里选用MySQL
在项目中settings.py配置:
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'testone',
        'USER': 'joker',
        'PASSWORD': 'xxx2',
        'HOST': '127.0.0.1',
        'PORT': '3306'
    }
}

三 新建项目-用来之后测试

1.) 使用虚拟环境,之后选择一个,我这里使用自己创建好的
	workon my-cross
2.) 创建django项目
	django-admin startproject testone 
3.) 在mysql中创建一个数据库 这里和上面的配置NAME‘必须对应  ,testone,

四 开发流程初探

1.) 在models.py中定义模型类,要求继承models.Model
2.) 把应用加入settings.py文件的installed_app项
3.) 生成迁移文件
4.) 执行迁移文件
5.) 使用模型类进行数据库的增删改查操作。

五 定义模型

在模型中定义属性,会生成表中的字段
django根据属性的类型确定一下信息:
	1)当前选择的数据库支持字段的类型
	2)渲染管理表单时使用的默认html空间
	3)在管理站点最低限度的验证
django会为表增加自动增长字段的主键列,如果自行设置了主键列,默认就不生成
属性命名限制:
	1. 不能是python的保留字
	2. 由于django的查询方式,不允许使用连续的下划线

(1) 创建一个应用-用来之后的测试

python manage.py startapp booktest

创建了一个booktest的应用,
将应用加入到settings.py中

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'booktest' #新增
]

(2) 定义属性:

定义属性时,需要字段类型
字段类型被定义在django.db.models.fields目录下,为了方便使用,被导入到django.db.models中
使用方式
	1. 导入from django.db import models
	2. 通过models.Field创建字段类型的对象,赋值给属性
对于重要的数据都做逻辑删除,不做物理删除,实现方法是定义isDelete属性,类型为BooleanField,默认值为False

(3)字段类型、选项和关系:
https://docs.djangoproject.com/zh-hans/2.1/ref/models/fields/

(4)元数据

在模型类中定义类Meta,用来设置元信息
元信息:
	db_table:定义数据表名称,使用小写。
	ordering:对象的默认排序字符,获取对象的列表时使用,接受属性构成的里列表
		可以加  -  , 不加  - 表示正序

(5)添加models.py中的类

from django.db import models

# Create your models here.
class BookInfo(models.Model):
    title = models.CharField(max_length=20)
    public = models.DateTimeField()
    reads = models.IntegerField(default=0)
    commet = models.IntegerField(null=False)
    isDelete = models.BooleanField(default=False)

    class Meta:
        db_table = 'bookinfo'


class HeroInfo(models.Model):
    name = models.CharField(max_length=10)
    gender = models.BooleanField(default=True)
    content = models.CharField(max_length=1000)
    isDelete = models.BooleanField(default=False)
    book = models.ForeignKey(BookInfo,on_delete=models.CASCADE)

"""测试
   insert into bookinfo(title,public,reads,commet,isDelete) values
    ('射雕英雄传','1980-05-01',12,34,0),
    ('天龙八部','1986-07-24',46,32,0),
    ('笑傲江湖','1995-12-14',30,50,0);
"""
"""
insert into booktest_heroinfo(name,gender,book_id,content,isDelete) values
('郭靖',1,1,'降龙十八章',0),
('黄蓉',0,1,'打狗棒法',0),
('黄药师',1,1,'弹指神通',0),
('欧阳锋',1,1,'蛤蟆功',0),
('梅超风',0,1,'九阴白骨爪',0),
('乔峰',1,2,'降龙掌',0),
('段誉',1,2,'六脉神剑',0),
('虚竹',1,2,'六阳掌',0),
('王语嫣',0,2,'勾魂夺魄',0),
('令狐冲',1,3,'独孤九剑',0),
('任盈盈',0,3,'谈情说爱',0)
"""

生成迁移文件和执行迁移:

python manage.py makemigrations
python manage.py migrate

六 模型成员

(1) 类的属性

· objects:是Manager类型的对象,用于数据库及进行交互
· 当定义模型类时没有制定管理器,则django会为模型类提供要给名为objects的管理器
· 支持明确指定模型类的管理器
class  BookInfo(models.Model):
	...
	books = models.Manager() #自定义管理器

当为模型类指定管理器后,django不再为模型类生成名为objects的默认管理器
(2) 管理器Manager

· 管理器是django的模型进行数据库的操作的接口,django每个模型都有一个管理器
· 自定义管理器:
	一:向管理器类中添加额外方法,见下面"创建对象 "中的方式二
	二:修改挂力气返回的数据集:重写get_queryset方法 
class BookInfoManager(models.Manager):
	def get_queryset(self):
		return super(BookInfomanager,self).get_queryset().filter(isDelete=False)
		
class BookInfo(models.Model):
	...
	books = models.BookInfoManager() #自定义管理器

(3)创建对象

· 当创建对象时,django不会对数据库进行读写操作
· 调用save()方法与数据库进行交互,将对象保存到数据库中

(4) 模型类的创建方法:

class BookInfo(models.Model):
    title = models.CharField(max_length=20)
    public = models.DateTimeField()
    reads = models.IntegerField(default=0)
    commet = models.IntegerField(null=False)
    isDelete = models.BooleanField(default=False)

    class Meta:
        db_table = 'bookinfo'
    
    # 模型类的创建方法:
    # 第一种:使用类方法(也可以使用对象方法)
    @classmethod
    def create(cls,title,public,reads,commet,isDelete):
        book = BookInfo()
        book.title = title
        book.public = public
        book.reads = reads
        book.commet = commet
        book.isDelete = isDelete
        return book
  #或者在自定义管理其中定义个create方法。

七 模型查询

在django中ORM就是django中的管理器,它来帮助我们操作数据库。

· 查询集表示从数据库中获取的对象集合
· 查询集可以包含零个、一个或多个过滤器
· 过滤器基于所给的参数显示查询结果
· 从sql的角度来说,查询集合select语句等价,过滤器类似where和limite等

(1) 查询集

· 在管理器上调用过滤器方法返回查询集
· 查询集经过过滤器筛选后返回新的查询集,因此可以写成链式过滤
· 惰性执行: 创建查询集不会带来任何数据库的访问,直到调用数据时,才会访问数据库库
· 何时对查询及求值: 迭代,序列化,与if合用
· 返回查询集的方法,称为过滤器
	all()
	filter()
	exclude()
	order_by()
	values():一个对象构成一个字典,然后构成一个列表返回。

写法:

filter(键1 = 值1 ,键2 = 值2 )
等同:
filter(键1 = 值1 ).filter(键2 = 值2 )

测试:python manage.py shell

>>> from booktest.models import  BookInfo
>>> BookInfo.objects.values() #这样就打印了结果

返回单个值的方法:

· get(): 返回单个满足条件的对象
		如果未找到,报异常
		如果返回多条,报异常
· count():返回当前查询的总条数
· first(0 返回第一个对象
· last() 
· exists():判断查询集中是否有数据u,如果有则返回true

限制查询集

· 查询及返回列表,可以使用下标的方式进行限制,等同于sql中的limit和offset子句
· 注意: 不支持负数索引
· 使用下标后返回一个新的查询集,不会立即执行查询
. 如果获取一个对象,直接使用[0],等同于[0:1].get() ,但是如果没有数据,[0]会引发indexError一次,[0:1].get()引发doesnotExist异常

查询集的缓存:

· 每个查询都包含一个缓存来最小化对数据库的访问
· 在新建的查询集中,缓存为空,首次对查询集求职时,会发生数据库查询,django会将查询的结果存在查询
集的缓存中,并返回请求的结果,接下来对查询集求职将重用缓存的结果

情况一: 构成了连个查询集,无法重用缓存,每次查询都会与数据库进行一次交换,增加负载

print([e.title for e in Entry.objects.all()])
print([e.title for e in Entry.objects.all()])

情况二:两次循环使用同一个查询集,第二次使用缓存中的数据

querylist = Entry.objects.all()
print([e.title for e in Entry.objects.all()])
print([e.title for e in Entry.objects.all()])

何时查询集不会被缓存: 当子对查询集的部分进行求值是会检查缓存,如果这部分不再缓存中,那么接下来的查询返回的记录将不会被缓存,这意味着使用索引来限制查询集将不会填充缓存。

字段查询

· 实现where子句,作为方法filter() 、exclude() 、get()参数
· 语法:属性名称_比较运算符 = 值
· 表示两个下划线,左侧是属性名称,右侧是比较类型
· 对于外键,使用属性名_id表示外键的原始值
· 转义 :like语句中使用%, 匹配数据中的%,在过滤器中直接写,如:
filter(title__contains="%")等价于where title like '%\%%'表示查找标题中包含%的

比较运算符:
默认有:exact:表示判断是否相等,大小写敏感,如果没有写 比较运算符,表示判断相等

>>> BookInfo.objects.filter(isDelete = False)
<QuerySet [<BookInfo: BookInfo object (1)>, <BookInfo: BookInfo object (2)>, <BookInfo: BookInfo object (3)>]>
>>> BookInfo.objects.filter(isDelete = True)
<QuerySet []>

包含:contains:是否包含,大小写敏感

>>> BookInfo.objects.filter(title__contains="天龙八部")
<QuerySet [<BookInfo: BookInfo object (2)>]>

startswith ,endswith:以value开头或结尾,大小写敏感

>>> BookInfo.objects.exclude(title__endswith="部")
<QuerySet [<BookInfo: BookInfo object (1)>, <BookInfo: BookInfo object (3)>]>

isnull, isnotnull:是否为null

在前面加个i表示不区分大小写,iexact,icontains,istartswith,iendswith
in:是否在包含范围内

filter(id__in=[1,2,3,4])

gt ,gte,lt,lte:大于,大于等于,小于,小于等于

filter(id__gt=3)

year,month,day,week_day,hour,minute,seconde:对日期类型的属性进行运算

filter(public__year=1980)
filter(public__gt = date(1980,12,31))

跨关联关系的查询:处理join查询
语法:模型类名<属性名><比较运算符>
注:可以没有__<比较>部分,表示等于,结果同inner join
可反向使用,即在关联的两个模型中都可以使用

	filter(heroinfo__content__contains="八" )

查询的快捷方式:pk,pk表示primary key,默认主键是id

filter(pk__lt =6)

聚合函数:

· 使用aggregate()函数返回聚合函数的值
· 函数: Avg, Count ,Max ,Min ,Sum

from django.db.models import Max
maxDate = list.aggregate(Max('public'))

F对象
可以使用模型的字段A与字段B进行比较,如果A写在等号的左侧,则B出现在等号的右侧,需要通过F对象构造

list.filter(read_gte=F('commet'))

Q对象:

· 过滤器的方法中关键参数查询,会合并为And进行
· 需要进行or查询,使用Q()对象
· Q对象(django.db.models,Q)用于封装一组关键字参数,这些参数与 比较运算符中的相同。

#可以使用&( and) 和 | (or)操作
#~表示去放(~Q(pk__lt=6))
from django.db.models import Q
list.filter(pk__lt=6).filter(commet__gt=10) 
list.filter(Q(pk__lt)=6 | Q(commet__gt=10))

八 增删改查示例

查-

models.UserInfo.objects.all()
models.UserInfo.objects.all().values('user')    #只取user列
models.UserInfo.objects.all().values_list('id','user')    #取出id和user列,并生成一个列表
models.UserInfo.objects.get(id=1)
models.UserInfo.objects.get(user='yangmv')

增:

models.UserInfo.objects.create(user='yangmv',pwd='123456')
或者
obj = models.UserInfo(user='yangmv',pwd='123456')
obj.save()
或者
dic = {'user':'yangmv','pwd':'123456'}
models.UserInfo.objects.create(**dic)

models.UserInfo.objects.filter(user='yangmv').delete()

models.UserInfo.objects.filter(user='yangmv').update(pwd='520')
或者
obj = models.UserInfo.objects.get(user='yangmv')
obj.pwd = '520'
obj.save()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值