传智博客的python的笔记

数据库配置

ORM简介

  • MVC框架中包括一个重要的部分,就是ORM,它实现了数据模型与数据库的解耦,即数据模型的设计不需要依赖于特定的数据库,通过简单的配置就可以轻松更换数据库
  • ORM是“对象-关系-映射”的简称,主要任务是:
    • 根据对象的类型生成表结构
    • 将对象、列表的操作,转换为sql语句
    • 将sql查询到的结果转换为对象、列表
  • 这极大的减轻了开发人员的工作量,不需要面对因数据库变更而导致的无效劳动
  • Django中的模型包含存储数据的字段和约束,对应着数据库中唯一的表

使用MySql数据库

  • 在settings.py文件中,通过DATABASES项进行数据库设置
  • django支持的数据库包括:sqlite、mysql等主流数据库
  • Django默认使用SQLite数据库
  • 在虚拟环境中安装mysql包
1
pip install mysql-python
  • 在mysql中创建数据库
1
create databases test2 charset=utf8
  • 打开settings.py文件,修改DATABASES项
1
2
3
4
5
6
7
8
9
10
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'test2',
'USER': '用户名',
'PASSWORD': '密码',
'HOST': '数据库服务器ip,本地可以使用localhost',
'PORT': '端口,默认为3306',
}
}

开发流程

  1. 在models.py中定义模型类,要求继承自models.Model
  2. 把应用加入settings.py文件的installed_app项
  3. 生成迁移文件
  4. 执行迁移生成表
  5. 使用模型类进行crud操作,crud是指在做对数据的增加(Create)、读取查询(Retrieve)、更新(Update)和删除(Delete)

使用数据库生成模型类

1
python manage.py inspectdb > booktest/models.py

模型的定义

定义模型

  • 在模型中定义属性,会生成表中的字段
  • django根据属性的类型确定以下信息:
    • 当前选择的数据库支持字段的类型
    • 渲染管理表单时使用的默认html控件,html中post的数据的接受
    • 在管理站点最低限度的验证
  • django会为表增加自动增长的主键列,每个模型只能有一个主键列,如果使用选项设置某属性为主键列后,则django不会再生成默认的主键列
  • 属性命名限制
    • 不能是python的保留关键字
    • 由于django的查询方式,不允许使用连续的下划线,仅允许单个下划线

定义属性

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

字段类型

  • AutoField:一个根据实际ID自动增长的IntegerField,通常不指定默认为pk
    • 如果不指定,一个主键字段将自动添加到模型中
  • BooleanField:true/false 字段,此字段的默认表单控制是CheckboxInput
  • NullBooleanField:支持null、true、false三种值
  • CharField(max_length=字符长度):字符串,默认的表单样式是 TextInput
  • TextField:大文本字段,一般超过4000使用,默认的表单控件是Textarea
  • IntegerField:整数
  • DecimalField(max_digits=None, decimal_places=None):使用python的Decimal实例表示的十进制浮点数
    • DecimalField.max_digits:位数总数
    • DecimalField.decimal_places:小数点后的数字位数
  • FloatField:用Python的float实例来表示的浮点数
  • DateField[auto_now=False, auto_now_add=False]):使用Python的datetime.date实例表示的日期
    • 参数DateField.auto_now:每次保存对象时,自动设置该字段为当前时间,用于”最后一次修改”的时间戳,它总是使用当前日期,默认为false
    • 参数DateField.auto_now_add:当对象第一次被创建时自动设置当前时间,用于创建的时间戳,它总是使用当前日期,默认为false
    • 该字段默认对应的表单控件是一个TextInput. 在管理员站点添加了一个JavaScript写的日历控件,和一个“Today”的快捷按钮,包含了一个额外的invalid_date错误消息键
    • auto_now_add, auto_now, and default 这些设置是相互排斥的,他们之间的任何组合将会发生错误的结果
  • TimeField:使用Python的datetime.time实例表示的时间,参数同DateField
  • DateTimeField:使用Python的datetime.datetime实例表示的日期和时间,参数同DateField
  • FileField:一个上传文件的字段,一般不用这个,通常上传到服务器,记录路径
  • ImageField:继承了FileField的所有属性和方法,但对上传的对象进行校验,确保它是个有效的image,也不用

字段选项

在字段对象时通过关键字参数指定,实现对字段的约束

  • null:如果为True,Django 将空值以NULL 存储到数据库中,默认值是 False,NULL值尽量不要存入数据库
  • blank:如果为True,则该字段允许传入数据库时不填写,默认值是 False
    • 对比:null是数据库范畴的概念,blank是表单验证证范畴的
  • db_column:字段的名称,如果未指定,则把属性的名称作为数据库字段的名称 ,不影响在danjo对数据的操作
  • db_index:若值为 True, 则在表中会为此字段创建索引
  • default:默认值,数据库不添加
  • primary_key:若为 True, 则该字段会成为模型的主键字段
  • unique:如果为 True, 这个字段在表中必须有唯一值

关系

  • 关系的类型包括
    • ForeignKey:一对多,将字段定义在多的端中
    • ManyToManyField:多对多,将字段定义在两个表中
    • OneToOneField:一对一,将字段定义在任意一端中
  • 可以维护递归的关联关系,使用’self’指定,详见“自关联”
  • 访问得到的对应的对象

    • 用一访问多:对象.模型类小写_set

      1
      bookinfo.heroinfo_set
    • 用一访问一:对象.模型类小写

      1
      heroinfo.bookinfo
    • 访问id:对象.属性_id

      1
      2
      heroinfo.book_id
      heroinfo.book.id

元选项

  • 在模型类中定义类Meta,用于设置元信息
  • 元信息db_table:定义数据表名称,推荐使用小写字母,数据表的默认名称
1
_
  • ordering:对象的默认排序字段,获取对象的列表时使用,接收属性构成的列表
1
2
3
4
class BookInfo(models.Model):
...
class Meta():
ordering = ['id']
  • 字符串前加-表示倒序,不加-表示正序
1
2
3
4
class BookInfo(models.Model):
...
class Meta():
ordering = ['-id']
  • 排序会增加数据库的开销

模型的成员

类的属性

管理器Manager

  • objects:是Manager类型的对象,用于与数据库进行交互
  • 当定义模型类时没有指定管理器,则Django自动为为模型类提供一个名为objects的管理器
  • 模型类的管理器可以自己指定,作为属性
1
2
3
class BookInfo(models.Model):
...
books = models.Manager()
  • 当为模型类指定管理器后,django不再为模型类生成名为objects的默认管理器
  • 管理器是Django的模型进行数据库的查询操作的接口,Django应用的每个模型都拥有至少一个管理器
  • 自定义管理器类主要用于两种情况
  • 情况一:向管理器类中添加额外的方法:见下面“创建对象”中的方式二
  • 情况二:修改管理器返回的原始查询集:重写get_queryset()方法
1
2
3
4
5
6
7
class BookInfoManager(models.Manager):
def get_queryset(self):
# super() 调用父类的方法,多重继承传入要调用的前一个
return super(BookInfoManager, self).get_queryset().filter(isDelete=False)
class BookInfo(models.Model):
...
books = BookInfoManager()

实例化

创建对象

  • 当创建对象时,django不会对数据库进行读写操作
  • 调用save()方法才与数据库交互,将对象保存到数据库中
  • 使用关键字参数构造模型对象很麻烦,推荐使用下面的两种之式
  • 说明:_ init _方法已经在基类models.Model中使用,在自定义模型中无法使用,
  • 方式一:在模型类中增加一个类方法
1
2
3
4
5
6
7
8
9
10
11
12
class BookInfo(models.Model):
...
@classmethod
def create(cls, title, pub_date):
book = cls(btitle=title, bpub_date=pub_date)
book.bread=0
book.bcommet=0
book.isDelete = False
return book
引入时间包:from datetime import *
调用:book=BookInfo.create("hello",datetime(1980,10,11));
保存: 大专栏  DjangoModelsbook.save()
  • 方式二:在自定义管理器中添加一个方法
  • 在管理器的方法中,可以通过self.model来得到它所属的模型类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class BookInfoManager(models.Manager):
def create_book(self, title, pub_date):
book = self.model()
book.btitle = title
book.bpub_date = pub_date
book.bread=0
book.bcommet=0
book.isDelete = False
return book class BookInfo(models.Model):
...
books = BookInfoManager()
调用:book=BookInfo.books.create_book("abc",datetime(1980,1,1))
保存:book.save()
  • 在方式二中,可以调用self.create()创建并保存对象,不需要再手动save()
1
2
3
4
5
6
7
8
9
10
class BookInfoManager(models.Manager):
def create_book(self, title, pub_date):
book = self.create(btitle = title,bpub_date = pub_date,bread=0,bcommet=0,isDelete = False)
return book class BookInfo(models.Model):
...
books = BookInfoManager()
调用:book=Book.books.create_book("abc",datetime(1980,1,1))
查看:book.pk

模型类更改后如果迁移失败,删除迁移文件在迁移

实例的属性

  • DoesNotExist:在进行单个查询时,模型的对象不存在时会引发此异常,结合try/except使用

实例的方法

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

模型的查询

基本概念

  • 查询集表示从数据库中获取的对象集合
  • 查询集可以含有零个、一个或多个过滤器
  • 过滤器基于所给的参数限制查询的结果
  • 从Sql的角度,查询集和select语句等价,过滤器像where和limit子句
  • 模型查询的主要内容
    • 查询集
    • 字段查询:比较运算符,F对象,Q对象

查询集

  • 在管理器上调用过滤器方法会返回查询集
  • 查询集经过过滤器筛选后返回新的查询集,因此可以写成链式过滤
  • 惰性执行:创建查询集不会带来任何数据库的访问,直到调用数据时,才会访问数据库
  • 查询集在调用数据时会进行缓存,两种情况不会
    • 未存入变量
    • 第一次使用[1:10]限制,第二次取[11:20]的数据不会被缓存
  • 何时对查询集求值:迭代,序列化,与if合用
  • 返回查询集的方法,称为过滤器

查询集

返回查询集的方法,称为过滤器

  • 返回多个值,列表或者字典
    • all() 返回所有
    • filter() 返回过滤的结果
    • exclude() 返回未被过滤的值
    • order_by() 排序
    • values():一个对象构成一个字典,然后构成一个列表返回
    • 写法:

      filter(键1=值1,键2=值2)
      逻辑与的关系,等价于
      filter(键1=值1).filter(键2=值2)

  • 返回单个值
    • get():返回单个满足条件的对象
      • 如果未找到会引发”模型类.DoesNotExist”异常
      • 如果多条被返回,会引发”模型类.MultipleObjectsReturned”异常
    • count():返回当前查询的总条数
    • first():返回第一个对象
    • last():返回最后一个对象
    • exists():判断查询集中是否有数据,如果有则返回True
    • aggregate(): 返回聚合函数的值,可用函数:Avg,Count,Max,Min,Sum,需要使用下面的语句引用,Count一般直接使用上面的
      1
      2
      from django.db.models import Max
      maxDate = list.aggregate(Max('bpub_date'))
  • 查询集返回列表,可以使用下标的方式进行获取,但是不支持负索引
  • 如果获取一个对象,直接使用[0],等同于[0:1].get(),但是如果没有数据,[0]引发IndexError异常,[0:1].get()引发DoesNotExist异常

字段查询

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

比较运算符

是否包含值

  • exact:表示判等,大小写敏感;如果没有写“_ _比较运算符”,表示判等,通常使用等号
1
filter(isDelete=False)
  • contains:是否包含,大小写敏感
1
exclude(btitle__contains='传')
  • startswith、endswith:以value开头或结尾,大小写敏感
1
exclude(btitle__endswith='传')
  • isnull、isnotnull:是否为null
1
filter(btitle__isnull=False)
  • 在前面加个i表示不区分大小写,如iexact、icontains、istarswith、iendswith
  • in:是否包含在范围内
1
filter(pk__in=[1, 2, 3, 4, 5])

大小的比较

  • gt、gte、lt、lte:大于、大于等于、小于、小于等于
1
filter(id__gt=3)

日期的比较

  • year、month、day、week_day、hour、minute、second:对日期间类型的属性进行运算
1
2
filter(bpub_date__year=1980)
filter(bpub_date__gt=date(1980, 12, 31))

跨关联关系的查询

  • 跨关联关系的查询:处理join查询
    • 语法:模型类名_ <属性名> _<比较>
    • 注:可以没有__<比较>部分,表示等于,结果同inner join
    • 可返向使用,即在关联的两个模型中都可以使用
1
filter(heroinfo_ _hcontent_ _contains='八')

小技巧

  • 查询的快捷方式:pk,pk表示primary key,默认的主键是id
1
filter(pk__lt=6)

F对象

需要数据内部的比较,使用F对象,需要导入

  • 可以使用模型的字段A与字段B进行比较,如果A写在了等号的左边,则B出现在等号的右边,需要通过F对象构造
1
list.filter(bread__gte=F('bcommet'))
  • django支持对F()对象使用算数运算
1
list.filter(bread__gte=F('bcommet') * 2)
  • F()对象中还可以写作“模型类__列名”进行关联查询
1
list.filter(isDelete=F('heroinfo__isDelete'))
  • 对于date/time字段,可与timedelta()进行运算
1
list.filter(bpub_date__lt=F('bpub_date') + timedelta(days=1))

Q对象

进行或运算

  • 过滤器的方法中关键字参数查询,会合并为And进行
  • 需要进行or查询,使用Q()对象
  • Q对象(django.db.models.Q)用于封装一组关键字参数,这些关键字参数与“比较运算符”中的相同
1
2
from django.db.models import Q
list.filter(Q(pk_ _lt=6))
  • Q对象可以使用&(and)、|(or)操作符组合起来
  • 当操作符应用在两个Q对象时,会产生一个新的Q对象
1
2
list.filter(pk_ _lt=6).filter(bcommet_ _gt=10)
list.filter(Q(pk_ _lt=6) | Q(bcommet_ _gt=10))
  • 使用~(not)操作符在Q对象前表示取反
1
list.filter(~Q(pk__lt=6))
  • 可以使用&|~结合括号进行分组,构造做生意复杂的Q对象
  • 过滤器函数可以传递一个或多个Q对象作为位置参数,如果有多个Q对象,这些参数的逻辑为and
  • 过滤器函数可以混合使用Q对象和关键字参数,所有参数都将and在一起,Q对象必须位于关键字参数的前面

自连接

  • 对于地区信息,属于一对多关系,使用一张表,存储所有的信息
  • 类似的表结构还应用于分类信息,可以实现无限级分类
  • 新建模型AreaInfo,生成迁移
1
2
3
class AreaInfo(models.Model):
atitle = models.CharField(max_length=20)
aParent = models.ForeignKey('self', null=True, blank=True)
  • 访问关联对象
1
2
上级对象:area.aParent
下级对象:area.areainfo_set.all()

DjangoModels的更多相关文章

  1. Django-models进阶

    Django-models进阶 extra extra(select=None, where=None, params=None, tables=None, order_by=None, select ...

  2. django--models操作

    1.models的功能 操作数据库 提交验证 在django的admin中,使用的是modelForms所以在验证的时候,尽管在models后有error_ message参数也不会根据此来提示.具体 ...

  3. django-- Models

    数据库配置 django默认支持sqlite,MySQL,Oracle,postgresql数据库 如何将数据库设置为MySQL 将setting中的database修改: DATABASES = { ...

  4. Django--models一对多

    一对多--foreignkey 应用场景 当一张表中创建一行数据时,有一个单选的下拉框(可以被重复选择) 例如:创建用户信息时候,需要选择一个用户类型[普通用户][金牌用户][铂金用户]等. 创建表 ...

  5. Django--models多对多

    多对多--ManyToMany 应用场景 在某表中创建一行数据时,有一个可以多选的下拉框(一对一是单选框)例如:创建用户信息,需要为用户指定多个爱好 创建表 两种方法,一个是利用Django自动为多对 ...

  6. Django--models表操作

    需求 models对表的增删改查 知识点 1.基础操作 1.1  增 方法一 1 models.Tb1.objects.create(c1='xx', c2='oo')  #增加一条数据 1 2 di ...

  7. Django--models一对多实例

    需求 models一对多表的构建,创建数据,查询数据,数据前端展示等​. 速查 1.创建数据 1 2 all_data = obj.clean()  #{'username': u'user1', ' ...

  8. Django--models连表构建

    需求 models多表(一对多.多对多.一对一)的构建 速查 1.一对多 1 2 3 class User(models.Model):     name = models.CharField(max ...

  9. Django--models基础

    需求 了解models字段和参数​ 速查 models.py 1 2 3 class UserInfo(models.Model):     ctime = models.DateTimeField( ...

  10. Django-models & QuerySet API

    django中配置mysql数据库 1,首先配置settings.py. 一是在INSTALLED_APPS里面加入app名称: 二是配置数据库相关信息 INSTALLED_APPS = [ 'dja ...

随机推荐

  1. 吴裕雄--天生自然ShellX学习笔记:Shell 流程控制

    和Java.PHP等语言不一样,sh的流程控制不可为空,如(以下为PHP流程控制写法): <?php if (isset($_GET["q"])) { search(q); ...

  2. geodjango七日学习笔记 (7.30整理本地笔记上传到网络)

    第一天进行到现在,在开端的尾巴,想起来写一个学习笔记, 开发环境已搭好,用的是pycharm 环境是本机已有的interpreter python3.7   接下来要做的是新建一个geodjango项 ...

  3. PAT甲级——1073 Scientific Notation (20分)

    Scientific notation is the way that scientists easily handle very large numbers or very small number ...

  4. OutOfMemoryError异常

    1.Java堆溢出 Java堆用于存储对象实例,只要不断地创建对象,并且保证GC Roots到对象之间有可达路径来避免垃圾回收机制清除这些对象,就会在对象数量达到最大堆的容量限制后产生内存溢出异常. ...

  5. diverta 2019 Programming Contest 2自闭记

    A 签到(a-b problem不用贴了吧,以后atcoder小于300分题均不贴代码) B 发现选择的p,q一定是其中两点间的距离,于是可以O(n2)枚举两点,再O(n2)判断,其实可以做到O(n3 ...

  6. ant design for vue 刷新页面,根据当前路由选中相应菜单

    <a-menu theme="dark" mode="horizontal" class="menu__a" @select=&quo ...

  7. GCC的分支预测优化__builtin_expect

    智能指针笔记 GCC的原子操作函数 将流水线引入cpu,可以提高cpu的效率.更简单的说,让cpu可以预先取出下一条指令,可以提供cpu的效率.如下图所示: 取指令 执行指令 输出结果 取指令 执行 ...

  8. visual studio2019下静态链接库的制作

    创建静态库项目 项目名称为20199324lib // pch.h #ifndef __PCH__ #define __PCH__ extern int add(int a, int b);//ext ...

  9. 吴裕雄--天生自然 PYTHON3开发学习:SMTP发送邮件

    import smtplib smtpObj = smtplib.SMTP( [host [, port [, local_hostname]]] ) SMTP.sendmail(from_addr, ...

  10. IDEA中的常用插件安装以及使用的介绍

    IDEA中的lombok插件安装以及各注解的详细介绍 Grep Console 当你密密麻麻一大片的日志,去查看起来,很容易看花眼:这个工具正好解决了这个痛点,可以说它就是 IDEA 自带 Conso ...