一、自定义char字段
Django中没有char类型,但是可以自定义实现。
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):
# 限定生成的数据库表字段类型char,长度为max_length指定的值
return 'char(%s)' % self.max_length
二、choices参数
我们往数据库存数据,比如说存年龄,一般都是存0,1,用0和1表示男女,在做数据展示的时候才会对应成具体的汉字。这个时候choices就派上了用场了。
可以先用元组做一个对应关系,然后再在定义表的阶段给需要用到的字段指定这个参数:
choices = ((0, '女'), (1, '男'), (2, '保密'))
gender = models.IntegerField(choices=choices, default=2)
可以通过get_gender_display()拿到数字对应的汉字。具体是 get_字段名_display()
res = models.Product.objects.filter(id=1).first()
print(res.gender) # 只能拿到我存的01
print(res.get_gender_display()) # 获取编号对应的中文注释
三、F与Q查询
先准备一个表:
class Product(models.Model):
name = models.CharField(max_length=32)
price = models.DecimalField(max_digits=8, decimal_places=2)
# 售出
sale = models.IntegerField()
# 库存
reserve = models.IntegerField()
info = MyCharField(max_length=32, null=True) # 该字段可以为空
choices = ((0, '女'), (1, '男'), (2, '保密'))
gender = models.IntegerField(choices=choices, default=2)
# 为方便查看打印的结果,格式化一下输出
def __str__(self):
return '商品对象的名字:%s' % self.name
然后执行命令在数据库创建:
python36 manage.py makemigrations
python36 manage.py migrate
在tests.py文件中做测试,先做以下准备:
import os
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day59.settings")
import django
django.setup()
from app01 import models
然后在下面查询即可。
F查询
当我们要查的内容和条件都是要从数据库中获得时,就需要用到F()查询.
from django.db.models import F, Q
1、查询卖出数大于库存数的商品
res = models.Product.objects.filter(sale__gt=F('reserve')) print(res)
2、将所有的商品的价格提高100块
models.Product.objects.update(price=F('price')+100)
3、将所有商品的名字后面都加一个爆款
# 字符串拼接用Concat,需要先导入 from django.db.models.functions import Concat from django.db.models import Value models.Product.objects.update(name=Concat(F('name'),Value('爆款')))
Q查询
filter()等方法传入的用逗号隔开的条件是与的关系,如果想要它是或的关系就要用Q查询
- and:filter(Q(),Q())
- or:filter(Q()|Q())
- not:filter(~Q())
1、查询价格199且名字为衬衣爆款的商品
res = models.Product.objects.filter(Q(price=199),Q(name='衬衣爆款'))
2、查询价格199或名字是衬衣爆款的商品
res = models.Product.objects.filter(Q(price=199)|Q(name='衬衣爆款'))
3、查询名字不是衬衣爆款的商品
res = models.Product.objects.filter(~Q(name='衬衣爆款'))
需要注意的是,Q()与普通的参数混合使用时,应该把Q对象放在普通的过滤条件前面
例:查询名字不是衬衣爆款,且价格为199的商品
res = models.Product.objects.filter(~Q(name='衬衣爆款'),price=199)
Q对象补充(******):
通过Q().connector = 'or',可以将Q对象默认的and关系改为or
from django.db.models import F, Q q = Q() q.connector = 'or' # 通过这个参数可以将Q对象默认的and关系变成or q.children.append(('price', 199)) q.children.append(('name', '衬衣爆款')) res = models.Product.objects.filter(q) print(res)
四、事务
事务在写mysql的时候写过,主要是为了防止一些操作出错。
事务有四大特性(ACID):
- 原子性:atomicity
- 一致性:consistency
- 隔离线:isolation
- 持久性:durability
from django.db import transaction from django.db.models import F with transaction.atomic(): # 在with代码块写相应的事务操作 # 售出一件给库存减1 models.Product.objects.filter(pk=1).update(reserve=F('reserve')-1) # 给销量加1 models.Product.objects.filter(pk=1).update(sale=F('sale')+1) print('其他代码逻辑')
五、defer和only
only与defer查询拿到的结果都是一个对象,但两者是相反的。
res = models.Product.objects.values('name') print(res) # 列表套字典的queryset对象。name为键,对应的名字为值。 res = models.Product.objects.only('name') print(res) # 得到一个对象的列表,各个商品对象 res = models.Product.objects.defer('name') for i in res: print(i.name)
defer('id','name'):取出对象,字段除了id和name都有
only('id','name'):取的对象,只有id和name
如果点,依然能点出其它列,但是不要点了,因为取没有的列,会再次查询数据库。