Django models

Django—F查询与Q查询

F查询

Django 提供 F() 来做这样的比较。F() 的实例可以在查询中引用字段,来比较同一个 model 实例中两个不同字段的值。

查询出卖出数大于库存数的商品

from django.db.models import F
ret1=models.Product.objects.filter(maichu__gt=F(‘kucun‘))
print(ret1)

F可以帮我们取到表中某个字段对应的值来当作我的筛选条件,而不是我认为自定义常量的条件了,实现了动态比较的效果

Django 支持 F() 对象之间以及 F() 对象和常数之间的加减乘除和取模的操作。基于此可以对表中的数值类型进行数学运算

将每个商品的价格提高50块

models.Product.objects.update(price=F(‘price‘)+50)

如果要修改char字段咋办?

把所有书名后面加上‘新款‘,(这个时候需要对字符串进行拼接Concat操作,并且要加上拼接值Value)

from django.db.models.functions import Concat
from django.db.models import Value
ret3=models.Product.objects.update(name=Concat(F(‘name‘),Value(‘新款‘)))

Q查询

filter() 等方法中逗号隔开的条件是与的关系。 如果你需要执行更复杂的查询(例如OR语句),你可以使用Q对象

from django.db.models import Q
models.Product.objects.filter(Q(maichu__gt=100)|Q(price__lt=100))
查询 库存数是100 并且 卖出数不是0 的产品

models.Product.objects.filter(Q(kucun=100)&~Q(maichu=0))

我们可以组合&|  操作符以及使用括号进行分组来编写任意复杂的Q 对象。

同时,Q 对象可以使用~ 操作符取反,这允许组合正常的查询和取反(NOT) 查询。

查询产品名包含新款, 并且库存数大于60的

odels.Product.objects.filter(Q(kucun__gt=60), name__contains="新款")

查询函数可以混合使用Q 对象和关键字参数。所有提供给查询函数的参数(关键字参数或Q 对象)都将"AND”在一起。但是,如果出现Q 对象,它必须位于所有关键字参数的前面。

事务

事务的定义:将多个sql语句操作变成原子性操作,要么同时成功,有一个失败则里面回滚到原来的状态,保证数据的完整性和一致性(NoSQL数据库对于事务则是部分支持)

# 事务

原子性
一致性
隔离性
持久性
    # 买一本 跟老男孩学Linux 书
    # 在数据库层面要做的事儿
    # 1. 创建一条订单数据
    # 2. 去产品表 将卖出数+1, 库存数-1
    from django.db.models import F
    from django.db import transaction
    # 开启事务处理
    try:
        with transaction.atomic():
            # 创建一条订单数据
            models.Order.objects.create(num="110110111", product_id=1, count=1)
            # 能执行成功
            models.Product.objects.filter(id=1).update(kucun=F("kucun")-1, maichu=F("maichu")+1)
    except Exception as e:
        print(e)

only/defer

defer(‘id‘,‘name‘):取出对象,字段除了id和name都有
only(‘id‘,‘name‘):取的对象,只有id和name
如果点,依然能点出其它列,但是不要点了,因为取没有的列,会再次查询数据库

choice字段

class User(models.Model):
    name = models.CharField(max_length=32)
    password = MyCharField(max_length=32)
    choices = ((1,‘重点大学‘),(2,‘普通本科‘),(3,‘专科‘),(4,‘其他‘))
    education = models.IntegerField(choices=choices)

user_obj.education  # 拿到的是数字
user_obj.get_education_display()  # 固定用法 获取choice字段对应的注释

什么是表内自关联

表内自关联是指表内数据相关联的对象和表是相同字段,这样我们就直接用表内关联将外键关联设置成自身表的字段。同样表内关联也分一对多字段和多对多字段
例如:对于微博评论,每条评论都可能有子评论,但每条评的字段内容应该都是相同的,并且每条评论都只有一个父评论,这就满足了,一对多的情形。父评论为关联字段,可以对应多个子评论,这就是一对多的自关联。

创建自关联表(一对多情景)

在django项目的models中创建评论表。

#评论表
class Comment(models.Model):
    #评论的内容字段
    content=models.CharField(max_length=255)
    #评论的发布时间
    push_time=models.DateTimeField(auto_now_add=True)
    #关联父评论的id,可以为空
    pcomment = models.ForeignKey(to=‘self‘,null=True)
    def __str__(self):
        return self.content

添加数据,第一条数据关联字段为空,说明是父评论,第二条数据关联了第一条数据说明是第一条数据的字评论,同样后两条数据是是第二条数据的子评论

分享图片

接下来查找第一条数据的子评论:

#第一条数据的id是1,可以通过筛选父评论关联字段等于1的对象
print(Comment.objects.filter(pcomment_id=1))

    #根据子评论关联id正向查找父评论的内容
    print(Comment.objects.filter(pcomment_id=2).values(‘pcomment__content‘))



    #根据父评论的id反向查找子评论
    print(Comment.objects.filter(id=1).values(‘comment__id‘))

注意:外键关联是在子评论中,有关联字段的是子评论,子评论查父评论是正向,父评论查子评论是反向。

多对多表自关联

建立一张表,表字段为姓名以及朋友多对多字段,一个人可有多个朋友,也可以是多个人的朋友,找一个人的朋友是正向查找,找是某个人的朋友是反向查找。

class Person(models.Model):
    name = models.CharField(max_length=12)
    #人和人交朋友
    friends = models.ManyToManyField(to=‘self‘,symmetrical=False,related_name=‘ship‘)
    def __str__(self):
        return self.name

添加数据:

分享图片

分享图片

 # 查找沁阳的基友
    #正向查找关联字段__name
    print(Person.objects.filter(name=‘沁阳‘).values(‘friends__name‘))

    # 反向查找沁阳的基友
    # print(Person.objects.all().filter(ship__name=‘沁阳‘))

    # 查找王帅的基友
    # 正向查找关联字段__name,王帅是沁阳的朋友但王帅的朋友是空,因为王帅没有关联别人
    print(Person.objects.get(name=‘王帅‘).friends.all())

    #反向查找是王帅朋友的人,也是空
    print(Person.objects.filter(ship__name=‘王帅‘))


    # 基友是沁阳的那个人反向查找
    print(Person.objects.get(name=‘沁阳‘).ship.all())
    #基友是王帅的那个人反向查找
    # print(Person.objects.get(name=‘王帅‘).ship.all())

    # 基友含有沁阳的人反向
    print(Person.objects.filter(name=‘沁阳‘).values(‘ship__name‘))

注意:查找某人的朋友是正向,查找朋友里面有某人的人是反向查找


自定制多对多

from django.db import models


# Create your models here.
class UserInfo(models.Model):
    username = models.CharField(
        null=True ,
        db_column=‘user‘ ,
        max_length=32 ,
        db_index=True ,  # 只能加速查找
        # unique=True,   #加速查找,限制列值唯一
        # primary_key=True,#主键也是索引,加速查找,限制列值唯一(不能为空)
    )


class User(models.Model):
    username = models.CharField(max_length=32 , db_index=True)

    def __str__(self):
        return self.username


class Tag(models.Model):
    title = models.CharField(max_length=16)

    def __str__(self):
        return self.title

    m = models.ManyToManyField(
        to=‘User‘ ,
        through=‘UserToTag‘ ,
        through_fields=[‘u‘ , ‘t‘]
    )
    # 使用ManyToManyField只能在第三张表中创建三类数据


class UserToTag(models.Model):
    # nid=models.AutoField(primary_key=True)
    u = models.ForeignKey(to=‘User‘ , on_delete=models.CASCADE , )
    t = models.ForeignKey(to=‘Tag‘ , on_delete=models.CASCADE , )
    ctime = models.DateField()

    # 自定制多对多
    class Meta:
        unique_together = [
            (‘u‘ , ‘t‘) ,
        ]
相关文章
相关标签/搜索