Django之自定义字段,choices字段参数,F查询与Q查询,事务,查询时的defer和only

一、自定义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

如果点,依然能点出其它列,但是不要点了,因为取没有的列,会再次查询数据库。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值