F与Q查询
Django 提供 F() 来做这样的比较。F() 的实例可以在查询中引用字段,来比较同一个 model 实例中两个不同字段的值。
settings.py
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
# 'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'ORM2',
'PORT': 3306,
'HOST': '127.0.0.1',
'USER': 'root',
'PASSWORD': 123
}
}
init.py
import pymysql
pymysql.install_as_MySQLdb()
models.py
from django.db import models
# Create your models here.
class Product(models.Model):
name = models.CharField(max_length=32)
price = models.DecimalField(max_digits=8, decimal_places=2)
maichu = models.IntegerField()
kucun = models.IntegerField()
def __str__(self):
return '对象的名字:%s'%self.name
执行命令创建表
pycharm菜单-tools-run manage.py TASK
$ makemigrations
$ migrate
tests.py
from django.test import TestCase
# Create your tests here.
import os
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "ORM2.settings")
import django
django.setup()
from app01 import models
初始数据
F查询
查询卖出数大于库存数的商品
from django.db.models import F,Q
# F查询 给一个字段就能拿到字段的值
res=models.Product.objects.filter(maichu__gt=F('kucun'))
print(res)
将所有商品的价格提高100块
models.Product.objects.update(price=F('price')+100)
将所有商品的名字后面都加上一个爆款
from django.db.models.functions import Concat
from django.db.models import Value
models.Product.objects.update(name=Concat(F('name'),Value('爆款')))
Q查询
<1> 查询价格是288.88并且名字是衣服同款爆款的商品(与查询)
from django.db.models import Q
from django.db.models import Q
res = models.Product.objects.filter(Q(price='288.88'),Q(name='衣服爆款'))
# 这里 第一个Q参数后面必须是传字符串,如果传数字(Q(price=288.88)),无法查询出对象
print(res)
<2> 查询价格是288.88或者名字是帽子同款爆款的商品(或查询)
from django.db.models import Q
res = models.Product.objects.filter(Q(price='288.88') | Q(name='裤子爆款')) # or
print(res)
# <QuerySet [<Product: 对象的名字:衣服爆款>, <Product: 对象的名字:裤子爆款>]>
<3> 查询价格不是288.88并且名字是裤子爆款的商品
混合使用 需要注意的是Q对象必须放在普通的过滤条件前面
res=models.Product.objects.filter(~Q(price='288.88'),Q(name='裤子爆款'))
print(res)
<4> 查询价格不是288.88或者名字是裤子爆款的商品
res=models.Product.objects.filter(Q(name='裤子爆款')|~Q(price='288.88'))
print(res)
Q对象补充
Q的源码
class Q(tree.Node):
"""
Encapsulates filters as objects that can then be combined logically (using
`&` and `|`).
"""
# Connection types
AND = 'AND'
OR = 'OR'
default = AND
def __init__(self, *args, **kwargs):
super(Q, self).__init__(children=list(args) + list(kwargs.items()
Q本身就是一个类,实例化一个对象,将所有的条件传入children这个属性中,而children这个属性是是列表,将条件写成一个小元组的方式作为一个整体传入children这个列表,小元组的第一个元素是字段名,第二个元素是写希望字段名符合的条件
例如
Q=q()
q.children.append((‘字段名’,‘条件’))
<1> 查询价格是288.88或者名字是帽子同款爆款的商品
from django.db.models import F, Q
q = Q()
q.connector = 'or'
q.children.append(('price', '288.88'))
q.children.append(('name', '裤子爆款'))
res = models.Product.objects.filter(q) # # Q对象查询默认也是and
print(res)
<2> 查询价格是288.88或者名字是衣服爆款的商品
from django.db.models import F, Q
q = Q()
q.children.append(('price', '288.88'))
q.children.append(('name', '衣服爆款'))
res = models.Product.objects.filter(q) # # Q对象查询默认也是and
print(res)
事务
事务的ACID
原子性
一致性
隔离性
持久性
id=1的商品卖出去一件
from django.db import transaction
from django.db.models import F
with transaction.atomic():
# 在with代码块儿写你的事务操作
models.Product.objects.filter(id=1).update(kucun=F('kucun') - 1)
models.Product.objects.filter(id=1).update(maichu=F('maichu') + 1)
自定义ORM字段
models.py
from django.db import models
class MycharField(models.Field):
def __init__(self,max_length,*args,**kwargs):
self.max_length=max_length
super().__init__(max_length=max_length,*args,**kwargs)
def db_type(self,connection):
return 'char(%s)'%self.max_length
class Product(models.Model):
name = models.CharField(max_length=32) # 都是类实例化的对象
price = models.DecimalField(max_digits=8, decimal_places=2)
maichu = models.IntegerField()
kucun = models.IntegerField()
info=MycharField(max_length=32,null=True) # 该字段可以为空
def __str__(self):
return '对象的名字:%s'%self.name
执行manage.py命令
菜单-tools-Run manager.py Task
$ makemigrations
$ migrate
only与defer
res = models.Product.objects.filter(id=1).values('name').first()
print(res)
这个过程中执行了3条sql语句
(0.000) SELECT @@SQL_AUTO_IS_NULL; args=None
(0.000) SELECT VERSION(); args=None
(0.000) SELECT `app01_product`.`name` FROM `app01_product` WHERE `app01_product`.`id` = 1 LIMIT 21; args=(1,)
only
如果取only指定的字段,不去数据库取值,直接在应用程序的缓存中取值
案例1
res=models.Product.objects.filter(pk=1).only('name').first()
print(res.name)
这个过程执行了3条SQL语句
(0.000) SELECT @@SQL_AUTO_IS_NULL; args=None
(0.000) SELECT VERSION(); args=None
(0.000) SELECT `app01_product`.`id`, `app01_product`.`name` FROM `app01_product` WHERE `app01_product`.`id` = 1 ORDER BY `app01_product`.`id` ASC LIMIT 1; args=(1,)
案例2
res=models.Product.objects.filter(pk=1).only('name').first()
print(res.price)
这个过程中执行了4条SQL语句,因为price字段不在only里面配置,所以price字段的值是去数据库里面取
(0.000) SELECT @@SQL_AUTO_IS_NULL; args=None
(0.000) SELECT VERSION(); args=None
(0.000) SELECT `app01_product`.`id`, `app01_product`.`name` FROM `app01_product` WHERE `app01_product`.`id` = 1 ORDER BY `app01_product`.`id` ASC LIMIT 1; args=(1,)
(0.000) SELECT `app01_product`.`id`, `app01_product`.`price` FROM `app01_product` WHERE `app01_product`.`id` = 1; args=(1,)
defer
与only相反,如果取defer指定的字段,则是去数据库取值,其他的字段直接在应用程序的缓存中取值
案例1
res=models.Product.objects.filter(pk=1).defer('name').first()
print(res.name)
执行了4条SQL语句
(0.000) SELECT @@SQL_AUTO_IS_NULL; args=None
(0.000) SELECT VERSION(); args=None
(0.000) SELECT `app01_product`.`id`, `app01_product`.`price`, `app01_product`.`maichu`, `app01_product`.`kucun`, `app01_product`.`info` FROM `app01_product` WHERE `app01_product`.`id` = 1 ORDER BY `app01_product`.`id` ASC LIMIT 1; args=(1,)
(0.000) SELECT `app01_product`.`id`, `app01_product`.`name` FROM `app01_product` WHERE `app01_product`.`id` = 1; args=(1,)
案例2
res=models.Product.objects.filter(pk=1).defer('name').first()
print(res.price)
执行了3条SQL语句
(0.000) SELECT @@SQL_AUTO_IS_NULL; args=None
(0.000) SELECT VERSION(); args=None
(0.001) SELECT `app01_product`.`id`, `app01_product`.`price`, `app01_product`.`maichu`, `app01_product`.`kucun`, `app01_product`.`info` FROM `app01_product` WHERE `app01_product`.`id` = 1 ORDER BY `app01_product`.`id` ASC LIMIT 1; args=(1,)
字段
choices
models.py
from django.db import models
class Product(models.Model):
name = models.CharField(max_length=32) # 都是类实例化的对象
price = models.DecimalField(max_digits=8, decimal_places=2)
maichu = models.IntegerField()
kucun = models.IntegerField()
info=MycharField(max_length=32,null=True) # 该字段可以为空
choices=((1,'男'),(2,'女'),(3,'其他'))
gender=models.IntegerField(choices=choices,default=2)
def __str__(self):
return '对象的名字:%s'%self.name
更新字段操作
菜单-tools-Run manager.py Task
$ makemigrations
$ migrate
tests.py
import os
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "ORM2.settings")
import django
django.setup()
from app01 import models
res=models.Product.objects.filter(id=1).first()
print(res.get_gender_display()) # 获取编号对应的中文注释