ORM常用字段及参数

我们在使用Django框架开发web应用的过程中,不可避免地会涉及到数据的管理操作(如增、删、改、查),而一旦谈到数据的管理操作,就需要用到数据库管理软件,例如mysql、oracle、Microsoft SQL Server等。

为了解决上述问题,django引入了ORM的概念

ORM全称Object Relational Mapping,即对象关系映射

是在pymysq之上又进行了一层封装,对于数据的操作,我们无需再去编写原生sql

取代代之的是基于面向对象的思想去编写类、对象、调用相应的方法等,ORM会将其转换/映射成原生SQL然后交给pymysql执行

创建表

class Employee(models.Model): 	# 必须是models.Model的子类
id=models.AutoField(primary_key=True)
name=models.CharField(max_length=16)
gender=models.BooleanField(default=1)
birth=models.DateField()
department=models.CharField(max_length=30)
salary=models.DecimalField(max_digits=10,decimal_places=1)

django的orm支持多种数据库,如果想将上述模型转为mysql数据库中的表,需要settings.py中

DATABASES = {
'default': {
# 'ENGINE': 'django.db.backends.mysql',
'ENGINE': 'django.db.backends.mysql',
'NAME': 'day53',
'HOST': '127.0.0.1',
'PORT': 3306,
'USER': 'root',
'PASSWORD': '123123',
'CHARSET': 'utf8'
}
}

在链接mysql数据库前,必须先创建好数据库

修改django的orm默认操作数据库的模块为pymysql

在_init_.py文件下加入这个

import pymysql
pymysql.install_as_MySQLdb()

ORM常用字段

AutoField

int自增列,必须填入参数 primary_key=True。当model中如果没有自增列,则自动会创建一个列名为id的列。

IntegerField

一个整数类型,范围在 -2147483648 to 2147483647。(一般不用它来存手机号(位数也不够),直接用字符串存,)

CharField

字符类型,必须提供max_length参数, max_length表示字符长度。

这里需要知道的是Django中的CharField对应的MySQL数据库中的varchar类型,没有设置对应char类型的字段

DateField

日期字段,日期格式 YYYY-MM-DD,相当于Python中的datetime.date()实例。

DateTimeField

日期时间字段,格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ],相当于Python中的datetime.datetime()实例。

BooleanField()

给字段传布尔值,会对应成0/1

TextField()

文本类型

FileField()

字符串,路径保存在数据库,文件上传到指定目录,只存文件路径

upload_to = '指定文件路径'

给该字段传文件对象 文件会自动保存到upload_to指定的文件夹下,然后将路径保存到数据库

DecimalField(Field)

1、10进制小数 2、参数: max_digits,小数总长度 decimal_places,小数位长度

字段合集(争取记忆)

AutoField(Field)
- int自增列,必须填入参数 primary_key=True
BigAutoField(AutoField)
- bigint自增列,必须填入参数 primary_key=True 注:当model中如果没有自增列,则自动会创建一个列名为id的列
from django.db import models class UserInfo(models.Model):
# 自动创建一个列名为id的且为自增的整数列
username = models.CharField(max_length=32) class Group(models.Model):
# 自定义自增列
nid = models.AutoField(primary_key=True)
name = models.CharField(max_length=32) SmallIntegerField(IntegerField):
- 小整数 -32768 ~ 32767 PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
- 正小整数 0 ~ 32767
IntegerField(Field)
- 整数列(有符号的) -2147483648 ~ 2147483647 PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
- 正整数 0 ~ 2147483647 BigIntegerField(IntegerField):
- 长整型(有符号的) -9223372036854775808 ~ 9223372036854775807 BooleanField(Field)
- 布尔值类型 NullBooleanField(Field):
- 可以为空的布尔值 CharField(Field)
- 字符类型
- 必须提供max_length参数, max_length表示字符长度 TextField(Field)
- 文本类型 EmailField(CharField):
- 字符串类型,Django Admin以及ModelForm中提供验证机制 IPAddressField(Field)
- 字符串类型,Django Admin以及ModelForm中提供验证 IPV4 机制 GenericIPAddressField(Field)
- 字符串类型,Django Admin以及ModelForm中提供验证 Ipv4和Ipv6
- 参数:
protocol,用于指定Ipv4或Ipv6, 'both',"ipv4","ipv6"
unpack_ipv4, 如果指定为True,则输入::ffff:192.0.2.1时候,可解析为192.0.2.1,开启此功能,需要protocol="both" URLField(CharField)
- 字符串类型,Django Admin以及ModelForm中提供验证 URL SlugField(CharField)
- 字符串类型,Django Admin以及ModelForm中提供验证支持 字母、数字、下划线、连接符(减号) CommaSeparatedIntegerField(CharField)
- 字符串类型,格式必须为逗号分割的数字 UUIDField(Field)
- 字符串类型,Django Admin以及ModelForm中提供对UUID格式的验证 FilePathField(Field)
- 字符串,Django Admin以及ModelForm中提供读取文件夹下文件的功能
- 参数:
path, 文件夹路径
match=None, 正则匹配
recursive=False, 递归下面的文件夹
allow_files=True, 允许文件
allow_folders=False, 允许文件夹 FileField(Field)
- 字符串,路径保存在数据库,文件上传到指定目录
- 参数:
upload_to = "" 上传文件的保存路径
storage = None 存储组件,默认django.core.files.storage.FileSystemStorage ImageField(FileField)
- 字符串,路径保存在数据库,文件上传到指定目录
- 参数:
upload_to = "" 上传文件的保存路径
storage = None 存储组件,默认django.core.files.storage.FileSystemStorage
width_field=None, 上传图片的高度保存的数据库字段名(字符串)
height_field=None 上传图片的宽度保存的数据库字段名(字符串) DateTimeField(DateField)
- 日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] DateField(DateTimeCheckMixin, Field)
- 日期格式 YYYY-MM-DD TimeField(DateTimeCheckMixin, Field)
- 时间格式 HH:MM[:ss[.uuuuuu]] DurationField(Field)
- 长整数,时间间隔,数据库中按照bigint存储,ORM中获取的值为datetime.timedelta类型 FloatField(Field)
- 浮点型 DecimalField(Field)
- 10进制小数
- 参数:
max_digits,小数总长度
decimal_places,小数位长度 BinaryField(Field)
- 二进制类型
字段合集
</code></pre>
</details>
ORM字段与MySQL字段对应关系

对应关系:
'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字段参数

null

用于表示某个字段可以为空。

unique

如果设置为unique=True 则该字段在此表中必须是唯一的 。

db_index

如果db_index=True 则代表着为此字段设置索引。

default

为该字段设置默认值。

DateField和DateTimeField

auto_now_add

配置auto_now_add=True,创建数据记录的时候会把当前时间添加到数据库。

auto_now

配置上auto_now=True,每次更新数据记录的时候会更新该字段。

ORM表关系创建

ForeignKey

外键类型在ORM中用来表示外键关联关系,一般把ForeignKey字段设置在 '一对多'中'多'的一方。

ForeignKey可以和其他表做关联关系同时也可以和自身做关联关系。

示例

class Book(models.Model):
# id是自动创建的,可以不用写
title = models.CharField(max_length=64)
# price为小数字段 总共8位小数位占2位
price = models.DecimalField(max_digits=8,decimal_places=2)
	# 书籍与出版社 是一对多外键关系
publish = models.ForeignKey(to='Publish') # 默认关联字段就是出版社表的主键字段
# publish = models.ForeignKey(to=Publish)
# to后面也可以直接写表的变量名 但是需要保证该变量名在当前位置的上方出现

字段参数

to 设置要关联的表

to_field 设置要关联的表的字段

on_delete 当删除关联表中的数据时,当前表与其关联的行的行为

models.CASCADE 删除关联数据,与之关联也删除

db_constraint 是否在数据库中创建外键约束,默认为True。

OneToOneField

一对一字段

通常一对一字段用来扩展已有字段。(通俗的说就是一个人的所有信息不是放在一张表里面的,简单的信息一张表,隐私的信息另一张表,之间通过一对一外键关联)

示例

class Author(models.Model):
name = models.CharField(max_length=32)
phone = models.BigIntegerField()
# 一对一外键关系建立
author_detail = models.OneToOneField(to='AuthorDetail')
	class AuthorDetail(models.Model):
age = models.IntegerField()
addr = models.CharField(max_length=255)

字段参数

to 设置要关联的表

to_field 设置要关联的字段

on_delete 当删除关联表中的数据时,当前表与其关联的行的行为

ManyToManyField

用于表示多对多的关联关系。在数据库中通过第三张表来建立关联关系。

示例

class Book(models.Model):
# id是自动创建的,可以不用写
title = models.CharField(max_length=64)
# price为小数字段 总共8位小数位占2位
price = models.DecimalField(max_digits=8,decimal_places=2)
	# 书籍与出版社 是一对多外键关系
publish = models.ForeignKey(to='Publish') # 默认关联字段就是出版社表的主键字段
# publish = models.ForeignKey(to=Publish)
# to后面也可以直接写表的变量名 但是需要保证该变量名在当前位置的上方出现
	# 图书与作者   是多对多外键关系
authors = models.ManyToManyField(to='Author') # 书籍和作者是多对多关系
# authors字段是一个虚拟字段 不会真正的在表中创建出来
# 只是用来告诉django orm 需要创建书籍和作者的第三张关系表

### 多对多三种创建方式

1 全自动(较为常用)

class Book(models.Model):
title = models.CharField(max_length=32)
authors = models.ManyToManyField(to='Author')
# orm就会自动帮你创建第三张表 class Author(models.Model):
name = models.CharField(max_length=32)
"""
好处:第三张表自动创建
不足之处:第三张表无法扩展额外的字段

2 纯手动(了解)

class Book(models.Model):
title = models.CharField(max_length=32) class Author(models.Model):
name = models.CharField(max_length=32) class Book2Author(models.Model):
book = models.ForeignKey(to='Book')
author = models.ForeignKey(to='Author')
create_time = models.DateField(auto_now_add=True)
"""
好处在于第三表可以扩展额外的字段
不足之处:orm查询的时候会带来不便
"""

3 半自动(推荐)

		class Book(models.Model):
title = models.CharField(max_length=32)
authors = models.ManyToManyField(to='Author',through='Book2Author',through_fields=('book','author')) class Author(models.Model):
name = models.CharField(max_length=32)
books = models.ManyToManyField(to='Author',through='Book2Author',through_fields=('author','book')) class Book2Author(models.Model):
book = models.ForeignKey(to='Book')
author = models.ForeignKey(to='Author')
create_time = models.DateField(auto_now_add=True) """
好处在于第三步可以扩展任意的额外字段 还可以利用orm 正反向查询
不足之处:无法利用
add
set
remove
clear
虽然无法使用了 但是你还可以自己直接操作第三表
"""

# 单表查询
**在python脚本中调用Django环境**

在进行一般操作时先配置一下参数,使得我们可以直接在Django页面中运行我们的测试脚本

这样就可以直接运行你的test.py文件来运行测试

Django终端daySQL语句

如果你想知道你对数据库进行操作时,Django内部到底是怎么执行它的sql语句时可以加下面的配置来查看

在Django项目的settings.py文件中,在最后复制粘贴如下代码:

LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console':{
'level':'DEBUG',
'class':'logging.StreamHandler',
},
},
'loggers': {
'django.db.backends': {
'handlers': ['console'],
'propagate': True,
'level':'DEBUG',
},
}
}

配置好之后,再执行任何对数据库进行操作的语句时,会自动将Django执行的sql语句打印到pycharm终端上

补充:

除了配置外,还可以通过一点.query即可查看查询语句,具体操作如下:

SELECT `app01_book`.`id`, `app01_book`.`title`, `app01_book`.`price`, `app01_book`.`publish_time`, `app01_book`.`publish_id` FROM `app01_book`

queryset和objects对象

  1. queryset是查询集,就是传到服务器上的url里面的内容。Django会对查询返回的结果集QerySet进行缓存,这里是为了提高查询效率。

    也就是说,在你创建一个QuerySet对象的时候,Django并不会立即向数据库发出查询命令,只有在你需要用到这个QuerySet的时候才回去数据库查询。

  2. Objects是django实现的mvc框架中的数据层(model)m,django中的模型类都有一个objects对象,它是一个django中定义的QuerySet类型的对象,

    它包含了模型对象的实例。简单的说,objects是单个对象,queryset是许多对象。

QuerySet 可以被构造,过滤,切片,做为参数传递,这些行为都不会对数据库进行操作。只要你查询的时候才真正的操作数据库。

循环(Iteration):QuerySet 是可迭代的,在你遍历对象时就会执行数据库操作

for book_obj in Book.objects.all():
print(book_obj.title)

必知必会的16条

1 create()

返回值就是当前被创建数据的对象本身

res = models.Movie.objects.all()
from datetime import date # 日期也可以手动给(2020-01-08)
ctime = date.today()
models.Movie.objects.create(title='双子杀手', price=99, publish_time=ctime)

2 all()

res = models.Movie.objects.all()
# <Movie: 双子杀手>]>

3 filter()

 直接获取对象本身,当查询条件不存在的时候直接报错
res = models.Movie.objects.filter(pk=1)
# <QuerySet [<Movie: 双子杀手>]>

4 get()

res = models.Movie.objects.get(pk=1)
# 泰囧2 直接获取对象本身,不推荐使用,当查询条件不存在的时候直接报错

5 values()

获取指定字段对的数据

res = models.Movie.objects.values('title', 'price')
# <QuerySet [{'title': '泰囧2', 'price': Decimal('99.00')}, {'title': '双子杀手', 'price': Decimal('99.00')}]>

6 values_list()

获取指定字段对的数据,无标题版的

res = models.Movie.objects.values_list('title','price')
# <QuerySet [('泰囧2', Decimal('99.00')), ('双子杀手', Decimal('99.00'))]>

7 first()

取第一个元素对象

res = models.Movie.objects.filter().first()
# 泰囧2

8 last()

取最后一个元素对象

res = models.Movie.objects.last()
# 双子杀手

9 update()

更新数据

res = models.Movie.objects.filter(pk=1).update(title='当怪物来敲门', price=22)
# 1 返回值是受影响的行数

10 delete()

删除数据

res = models.Movie.objects.filter(pk=1).delete()
# (1, {'app01.Movie': 1}) 受影响的表及行数

11 count()

统计数据条数

res = models.Movie.objects.count()

12 order_by()

按照指定字段排序

res = models.Movie.objects.order_by('price') # 默认是升序
res = models.Movie.objects.order_by('-price') # 减号就是降序

13 exclude()

排除什么什么之外

res = models.Movie.objects.exclude(pk=1)

14 exists()

返回的是布尔值 判断前面的对象是否有数据 了解即可

res = models.Movie.objects.filter(pk=1000).exists()

15 reverse()

反转

res = models.Movie.objects.order_by('price').reverse()

16 distinct()

去重:去重的前提 必须是由完全一样的数据的才可以

res = models.Movie.objects.values('title','price').distinct()

双下划线查询

语法:字段名__方法名

使用:一般作为filter()的过滤条件

下表中示例语句,省略models.Books.objects.

方法 说明 示例
__gt 大于 filter(price__gt=500
__lt 小于 filter(price__lt=400)
__gte 大于等于 filter(price__gte=500)
__lte 小于等于 filter(price__lte=500)
__in 在...中 filter(price__in=[222,444,500])
__range 在某区间内,参数为[],包含两端 filter(price__range=(200,800))
__year 是某年 filter(publish_date__year='2019')
__month 是某月 filter(publish_date__month='1')

模糊查询

语法:字段名__方法名

使用:一般作为filter()参数

以下示例,省略models.Books.objects.

方法 说明 示例
__startswith 以某字符串开头 filter(title__startswith='三')
__endswith 以某字符串结束 filter(title__endswith='1')
__contains 包含某字符串 filter(title__contains='双')
__icontains 包含某字符串,但忽略大小写 filter(title__icontains='p')

多表查询

外键字段增删改查

models代码

from django.db import models


class Book(models.Model):
title = models.CharField(max_length=32)
price = models.DecimalField(max_digits=8,decimal_places=2)
publish_time = models.DateField(auto_now_add=True) # 该字段新增数据自动添加 无需考虑


# 出版社 一对多 外键字段建在多的一方
publish = models.ForeignKey(to='Publish')
# 作者 多对多 外键字段建在任意一方均可 推荐你建在查询频率较高的表
authors = models.ManyToManyField(to='Author')


# 库存数
# kucun = models.BigIntegerField(default=1000)
# # 卖出数
# maichu = models.BigIntegerField(default=1000)


def __str__(self):
return self.title


class Publish(models.Model):
name = models.CharField(max_length=32)
addr = models.CharField(max_length=64)


class Author(models.Model):
name = models.CharField(max_length=32)
age = models.IntegerField()


# 作者详情 一对一 外键字段建在任意一方均可 推荐你建在查询频率较高的表
author_detail = models.OneToOneField(to='AuthorDetail')


class AuthorDetail(models.Model):
phone = models.BigIntegerField()
addr = models.CharField(max_length=32)

一对多

一对多

# 1  直接写实际的表字段 publish_id
models.Book.objects.create(title='蜡笔小新',price=88,publish_id=2) #2 传虚拟字段
# 先查询关联的数据对象
publish_obj = models.Publish.objects.get(pk=1)
# 再将对象作为参数传给外键(定义中写到的外键,是一个虚拟字段)
models.Book.objects.create(title='蜡笔小新1',price=88,publish=publish_obj)

#1  把Book表里pk为5的publish_id改为1
models.Book.objects.filter(pk=5).update(publish_id=1) # 2 传虚拟字段
publist_obj = models.Publish.objects.get(pk=1)
models.Book.objects.filter(pk=5).update(publish=publist_obj)

models.Book.objects.filter(pk=6).delete()

外键字段在1.X版本中默认就是级联更新级联删除的

2.X版本中,则需要你自己手动指定

多对多

增add()

add专门给第三张关系表添加数据

括号内即可以传数字也可以传对象 并且都支持传多个

# 给书籍绑定作者关系
# 书籍和作者的关系是由第三张表组成,也就意味着你需要操作第三张表
# 书籍对象点虚拟字段authors就类似于已经跨到书籍和作者的第三张关系表中
# 1 传数字
book_obj = models.Book.objects.filter(pk=5).first()
# print(book_obj.authors)
book_obj.authors.add(4) # 给书籍绑定一个主键为4的作者
book_obj.authors.add(3,4) # 2 传对象
book_obj = models.Book.objects.filter(pk=5).first()
author_obj = models.Author.objects.get(pk=3)
book_obj.authors.add(author_obj)

删除remove()

移除书籍与作者的绑定关系

remove专门给第三张关系表移除数据

括号内即可以传数字也可以传对象 并且都支持传多个

book_obj = models.Book.objects.filter(pk=5).first()
book_obj.authors.remove(3,4) # 传对象
book_obj = models.Book.objects.filter(pk=5).first()
author_obj = models.Author.objects.get(pk=3)
book_obj.authors.remove(author_obj)

修改set()

set 修改书籍与作者的关系

括号内支持传数字和对象 但是需要是可迭代对象

book_obj = models.Book.objects.filter(pk=5).first()
book_obj.authors.set((3,)) #注意,这里需要传可迭代对象,数字加上括号加上逗号即可 # 传对象
book_obj = models.Book.objects.filter(pk=5).first()
author_obj = models.Author.objects.get(pk=4)
book_obj.authors.set((author_obj,))

清空clear()

清空书籍与作者关系,不需要任何参数

book_obj = models.Book.objects.filter(pk=5).first()
book_obj.authors.clear() # 去第三张表中清空书籍为5的所有数据

跨表查询

# 当以Book为基表时,称之为正向查询
Book(基表)-------正向---------->Publish
外键字段是否在当前数据对象中,如果在,查询另外一张关系表,叫正向 # 当以Publish为基表时,称之为反向查询
Book<-------反向----------Publish(基表)
外键字段是否在当前数据对象中,如果不在,查询另外一张关系表,叫反向 口诀
正向查询按外键字段
反向查询按表名小写

使用原生sql进行多表关联查询时无非两种方式:子查询、join连表查询,ORM里同样有两种查询方式(严格依赖正向、反向的概念)

基于对象的跨表查询(子查询)

正向查询 :对象.外键

book_obj = models.Book.objects.filter(pk=5).first()		#查询书籍pk为5的出版社名称
print(book_obj.publish) # 对象.外键即可得到关联的对象
book_obj = models.Book.objects.filter(pk=5).first()   #查询书籍pk为5的所有作者的姓名
print(book_obj.authors.all())
author_list = book_obj.authors.all()
for author_obj in author_list:
print(author_obj.name)
author_obj = models.Author.objects.filter(pk=3).first()		# 查询作者pk为3的电话号码
print(author_obj.author_detail)
print(author_obj.author_detail.phone)

正向查询的时候 当外键字段对应的数据可以有多个的时候需要加.all()

否则点外键字典即可获取到对应的数据对象

基于对象的反向查询,表名是否需要加 _set.all()

一对多和多对多的时候需要加

一对一不需要

基于双下划线跨表查询(链表查询)

反向查询 :对象.关联的表名小写 + _set

查询书籍pk为5的出版社名称
# 正向查询
res = models.Book.objects.filter(pk=5).values('publish__name') # 写外键字段 就意味着你已经在外键字段管理的那张表中 # 反向查询
res = models.Publish.objects.filter(book__pk=5) # 拿出版过pk为1的书籍对应的出版社
# res = models.Publish.objects.filter(bool__pk=1).values('name')
查询书籍pk为5的作者姓名和年龄
#正向查询
res = models.Book.objects.filter(pk=5).values('title', 'authors__name', 'authors__age') # 反向查询
res = models.Author.objects.filter(book__pk=1) # 拿出出版过书籍pk为1的作者
#res = models.Author.objects.filter(bool_pk=5).values('name', 'age', 'book__title')
查询作者是kai的年龄和手机号
#正向查询
res = models.Author.objects.filter(name='kai').values('age','author_detail__phone') #反向查询
res = models.AuthorDetail.objects.filter(author__name='kai') # 拿到jason的个人详情
#res=models.AuthorDetail.objects.filter(author__name='kai').values('phone','author__age')

只要表之间有关系,你就可以通过正向的外键字段 或者 反向的表名小写,连续跨表操作

聚合查询(分组查询)

# 需先导入模块
from django.db.models import Max,Min,Avg,Count,Sum

1、关键字:annotate

2、关键语法:QuerSet对象.annotate(聚合函数)

# 1.统计每一本书的作者个数
res = models.Book.objects.annotate(author_num=Count('authors')).values('title','author_num')
# 2.统计出每个出版社卖的最便宜的书的价格
res = models.Publish.objects.annotate(min_price=Min('book__price')).values('name','min_price','book__title')
# 3.统计不止一个作者的图书
res = models.Book.objects.annotate(author_num=Count('authors')).filter(author_num__gt=1).values('title')
# print(res)
# 4.查询各个作者出的书的总价格
res = models.Author.objects.annotate(price_sum=Sum('book__price')).values('name','price_sum')
# 5.如何按照表中的某一个指定字段分组

    res = models.Book.objects.values('price').annotate()  就是以价格分组

F与Q

F() 的用法

F() 的实例可以在查询中引用字段,来比较同一个 model 实例中两个不同字段的值>

# 需要导入模块
from django.db.models import F, Q
# 1.查询库存数大于卖出数的书籍
res = models.Book.objects.filter(kucun__gt=F('maichu'))
# 2.将所有书的价格提高100
res = models.Book.objects.update(price=F('price') + 100)

帮你获取到表中某个字段对应的值

Q() 的用法

filter() 等方法中逗号隔开的条件是与的关系

如果你需要执行更复杂的查询(例如OR语句),你可以使用Q对象

查询书的名字是python入门或者价格是1000的书籍
res = models.Book.objects.filter(Q(title='python入门'),Q(price=1000)) # 逗号是and关系
res = models.Book.objects.filter(Q(title='python入门')|Q(price=1000)) # |是or关系
res = models.Book.objects.filter(~Q(title='python入门')|Q(price=1000)) # ~是not关系

Q() 的高级用法

q = Q()
q.connector = 'or' # q对象默认也是and关系 可以通过connector改变or
q.children.append(('title','python入门'))
q.children.append(('price',1000)) res = models.Book.objects.filter(q) #~q取反
print(res)

# 特殊参数choices

1、定义字段时,指定参数choices

2、choices的值为元组套元组(事先定义好,一般在该表类中定义该字段之前定义)

3、每一个元组存放两个元素,形成一种对应关系

4、往数据库中存值时,该字段的值存为元组第一个元素即可

5、通过方式对象.get_字段名_display()获取对应的元组第二个元素值,当没有对应关系时,返回的是它本身

		class Userinfo(models.Model):
username = models.CharField(max_length=32)
gender_choices = (
(1,'男'),
(2,'女'),
(3,'其他'),
)
gender = models.IntegerField(choices=gender_choices)
# 该字段还是存数字 并且可以匹配关系之外的数字
record_choices = (('checked', "已签到"),
('vacate', "请假"),
('late', "迟到"),
('noshow', "缺勤"),
('leave_early', "早退"),
)
record = models.CharField("上课纪录", choices=record_choices, default="checked", max_length=64) user_obj = models.Userinfo.objects.get(pk=1)
print(user_obj.username)
print(user_obj.gender)
# 针对choices参数字段 取值的时候 get_xxx_display()
print(user_obj.get_gender_display())
# 针对没有注释信息的数据 get_xxx_display()获取到的还是数字本身
user_obj = models.Userinfo.objects.get(pk=4)
print(user_obj.gender)
print(user_obj.get_gender_display())

数据库查询优化

减少对数据库的操作,减轻数据库的压力

only与defer

orm惰性查询

orm内所有的sql查询语句,都是惰性操作,即当你需要使用查询结果时,才会真正去执行sql语句访问数据库,否则是不会执行查询的

可使用代码验证:

1、配置settings文件,使得当执行sql语句时,在终端打印sql命令

2、验证

# 只查询,不使用查询结果
models.User.objects.all()
# 将查询结果赋值给变量res
res = models.User.object.all() # 分别执行,查看终端的打印结果

only与defer

only查询:指定查询某字段是,将全部结果一次性取出来,以后再访问该字段数据时,直接从内存中拿即可,不需要再操作数据库

defer查询:指的是一次性获取指定字段之外的所有字段数据,封装到对象中,以后再访问这些字段数据时,直接从内存中拿即可,不需要再操作数据库

# 同样,可以配置settings,在终端中打印被执行的sql命令

# all()查询
res = models.User.objects.all() # 访问一次数据库,打印一条sql命令,获取所有的User表中的数据到内存 # only查询
res = models.User.objects.only(username) # 访问一次数据库,打印一条sql命令,仅仅获取username的所有数据到内存
for user_obj in res:
print(user_obj.username) # 直接从内存中获取,不访问数据库,不打印sql命令
print(user_obj.gender) # 每执行一次,就访问一次数据库,打印一次sql命令 # defer 查询
res = models.User.objects.defer(usernmae) # 访问一次数据库,打印一条sql命令,获取除了username之外的所有数据到内存
for user_obj in res:
print(user_obj.username) # 每执行一次,访问一次数据库,打印一条sql命令
print(user_obj.gender) # 直接从内存中获取,不访问数据库,不打印sql命令

select_related与prefetch_related

当表中有外键时,使用方法减轻数据库的压力

select_related:指定外键,将本表与该外键关联的表拼成一张表(inner join),并获取所有数据到内存,不能指定多对多关系的外键

prefetch_related:指定外键,先查询本表所有数据,再根据外键查询对应的数据表所有数据,相当于子查询,可以指定多个外键,即多个子查询

Django中如何开启事务

什么是事务?

Django框架本身提供了两种事务操作的用法。(针对mysql)

启用事务用法1:

from django.db import transaction
from rest_framework.views import APIView class OrderAPIView(APIView):
@transaction.atomic # 开启事务,当方法执行完以后,自动提交事务
def post(self, request):
pass #

启用事务用法2:

from django.db import transaction
from rest_framework.views import APIView class OrderAPIView(APIView):
def post(self,request):
....
with transation.atomic(): # 开启事务,当with语句执行完成以后,自动提交事务
pass # 数据库操作

在使用事务过程中,有时候会出现异常,当出现异常的时候,我们需要让程序停下来,同时回滚事务。

from django.db import transaction
from rest_framework.views import APIView
class OrderAPIView(APIView):
def post(self,request):
....
with transation.atomic():
# 设置事务回滚的标记点
sid = transation.savepoint() .... try:
....
except:
transation.savepoint_rallback(sid)

ORM常用字段及查询的更多相关文章

  1. Django框架之第六篇(模型层)--单表查询和必知必会13条、单表查询之双下划线、Django ORM常用字段和参数、关系字段

    单表查询 补充一个知识点:在models.py建表是 create_time = models.DateField() 关键字参数: 1.auto_now:每次操作数据,都会自动刷新当前操作的时间 2 ...

  2. 06 ORM常用字段 关系字段 数据库优化查询

    一.Django ORM 常用字段和参数 1.常用字段 models中所有的字段类型其实本质就那几种,整形varchar什么的,都没有实际的约束作用,虽然在models中没有任何限制作用,但是还是要分 ...

  3. ORM常用字段介绍

    Django中的ORM Django项目使用MySQL数据库 1. 在Django项目的settings.py文件中,配置数据库连接信息: DATABASES = { "default&qu ...

  4. Django(ORM常用字段)

    day68 参考:http://www.cnblogs.com/liwenzhou/p/8688919.html 1. Django ORM常用字段:             1. AutoField ...

  5. Django框架 之 ORM 常用字段和参数

    Django框架 之 ORM 常用字段和参数 浏览目录 常用字段 字段合集 自定义字段 字段参数 DateField和DateTimeField 关系字段 ForeignKey OneToOneFie ...

  6. python 之 Django框架(ORM常用字段和字段参数、关系字段和和字段参数)

    12.324 Django ORM常用字段 .id = models.AutoField(primary_key=True):int自增列,必须填入参数 primary_key=True.当model ...

  7. Django中ORM常用字段及字段参数

    Object Relational Mapping(ORM) ORM介绍 ORM概念 对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象与关系数据 ...

  8. Django orm常用字段和字段参数

    1.Object Relational Mapping(ORM) 1.1ORM介绍 ORM概念 对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象 ...

  9. ORM常用字段及方式

    创建小型数据库 模型层 ORM常用字段 AutoField int自增列,必须填入参数 primary_key=True.当model中如果没有自增列,则自动会创建一个列名为id的列. Integer ...

随机推荐

  1. SpringCloud全家桶学习之一阶段总结(一)

    一.概述 前几篇小博客记录了我学习SpringCloud组件的过程,并与工作中所用的Dubbo框架做了一点比较,基本组件:Eureka.Ribbon.Hystrix.Feign.Zuul.Config ...

  2. 【笔记2-环境配置及初始化】从0开始 独立完成企业级Java电商网站开发(服务端)

    准备工作 Linux系统安装 云服务器部署 概要 申请和配置 域名的购买.解析.配置.绑定流程 用户创建实操 环境安装及部署 JDK.Tomcat.Maven下载安装及配置 vsftpd下载安装及配置 ...

  3. DAY1小题

    F 求逆序对的板子题 #include<cstdio> #define ll long long using namespace std; ; ll a[maxn],r[maxn],n; ...

  4. elasticsearch数据组织结构

    elasticsearch数据组织结构 1.      mapping 1.1.    简介 mapping:意为映射关系,特别是指组织结构.在此语境中可理解为数据结构,包括表结构,表约束,数据类型等 ...

  5. html和css的重难点知识

    目录 html总难点总结: 1. 块级标签与内联标签的区别 1.1 块级标签: 1.2 内联标签: 2. 选择器 2.1 定义 2.2 选择器的分类 2.1 选择器的分类 3. css中margin, ...

  6. debezium、kafka connector 解析 mysql binlog 到 kafak

    目的: 需要搭建一个可以自动监听MySQL数据库的变化,将变化的数据捕获处理,此处只讲解如何自动捕获mysql 中数据的变化 使用的技术 debezium :https://debezium.io/d ...

  7. row_number over ()排序函数

    语法: row_number () over (排序规则)  计算每一行数据在结果集的行数 select ROW_NUMBER() over (order by FSalary) as 排序 ,*  ...

  8. 利用 Jenkins 持续集成 iOS 项目,搭建自动化打包环境

    ---恢复内容开始--- jenkins是一个广泛用于持续构建的可视化web工具,持续构建即各种项目的”自动化”编译.打包.分发部署.jenkins可以很好的支持各种语言(比如:Java, c#, P ...

  9. Bcrypt加密算法简介

    用户表的密码通常使用MD5等不可逆算法加密后存储,为防止彩虹表破解更会先使用一个特定的字符串(如域名)加密,然后再使用一个随机的salt(盐值)加密. 特定字符串是程序代码中固定的,salt是每个密码 ...

  10. problem :无法显示activemq的管理界面

    点击 Manage ActiveMQ broker 无法显示admin界面 解决方法:修改activemq.xml 和 jetty.xml文件 把所有0.0.0.0修改为127.0.0.1 成功: 账 ...