Django-orm:单表查询、基于对象和双下划线的多表操作、集合查询、分组查询、F查询和Q查询

############################################## 单表操作 ##############################################
简单查:
    models.User.objects.filter(id=3)               # queryset对象,相当于一个列表,放了一个或多个User对象
    models.User.objects.filter(id=3).first()    # User对象,相当于只去了queryset对象中的第一个

增:
    第一种:# 先创建数据,再保存
        user = models.User(username=‘alex‘,password=‘a654321‘)
        user.save()
    第二种:# 直接保存或先创建再保存
        1.方式一:
        models.User.objects.create(username=‘alex‘,password=‘a654321‘)
        2.方式二:
        dic={"username":"alex","password":‘a654321‘}
        models.Book.object.create(**dic)

删:
    方式一:# 删除所查出queryset对象中所有对象
        models.User.objects.filter(id=3).delete()
    方式二:# 删除所查出的user对象
        user = models.User.objects.filter(id=3).first()
        user.delete()

改:
    方式一:# 将修改所查到queryset对象中所有的对象
        models.User.objects.filter(id=3).update(username=‘egon‘,password=‘aa123‘)
    方式二:# 只修改所查到的user对象,一般在收集日志的时候用此方法,因为有save()动作
        user = models.User.objects.filter(id=3).first()
        user.username=‘egon‘
        user.password=‘aa123‘
        user.save()

查:
    查询相关API:
        <1>filter(**kwargs):      它包含了与所给筛选条件相匹配的对象
        <2>all():                 查询所有结果
        <3>get(**kwargs):         返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。
        #---------下面的方法都是对查询的结果再进行处理:比如 objects.filter().values()--------
        ‘‘‘
            **kwargs:代表以键值(字段=值)的方法传参
            *field:代表只传键(字段),不传值
        ‘‘‘
        <4>values(*field):        返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列 model的实例化对象,而是一个可迭代的字典序列
        <5>exclude(**kwargs):     它包含了与所给筛选条件不匹配的对象  # 可直接用,也可用在filter之后
        <6>order_by(*field):      对查询结果排序              # 只能用在queryset之后
        <7>reverse():             对查询结果反向排序          # 必须用在order_by之后
        <8>distinct():            从返回结果中剔除重复纪录  # 一般用在values之后,对某一字段进行去重
        <9>values_list(*field):   它与values()非常相似,它返回的是一个元组序列  # 将values()字典中的值拿了出来,组成元组
        <10>count():              返回数据库中匹配查询(QuerySet)的对象数量。  # 只能用在queryset对象之后
        <11>first():              返回第一条记录
        <12>last():               返回最后一条记录
        <13>exists():             如果QuerySet包含数据,就返回True,否则返回False。  # 只能用在queryset之后

    基于双下划线__的模糊查询:
        models.Tb1.objects.filter(id__lt=10, id__gt=1)   # 获取id大于1 且 小于10的值
        models.Tb1.objects.filter(id__in=[11, 22, 33])   # 获取id等于11、22、33的数据
        models.Tb1.objects.exclude(id__in=[11, 22, 33])  # not in
        models.Tb1.objects.filter(id__range=[1, 2])      # 范围bettwen and
        models.Tb1.objects.filter(name__contains="ven")  # name中包含ven的,对大小写敏感
        models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感
        ....startswith(以什么开头)
        ....istartswith(返回Bool值)
        ....endswith(以什么结尾)
        ....iendswith(返回Bool值)

# ****************小Tip***************
    1.user = models.User.objects.filter(id=3)
      print(user.query)  # 打印其原生SQL
    2.pk即id,pk指主键,一般id也作为主键
    3.models中,在创建一对一和一对多关系时,需要添加约束:"on_delete=models.CASCADE",意为在删除被关联字段时,必须删除其关联的所有字段,称为“级联删除”
    4.正向查询:关联字段在当前表中,从当前表向外查
      反向查询:关联字段不在当前表中,从当前表向外查
# ************************************

############################################## 多表操作 ##############################################
多表操作相对于单表来说只是多了约束条件,只要在操作时考虑到相关联的表就行了

例:‘‘‘
    author表:name
    detail表:age,sex,addr
    book表:name,pub_date
    publisher表:name,addr

    author和detail之间存在一对一关系,其关联字段‘det_auth‘写在detail中
    book和publisher之间存在一对多关系,其关联字段‘book_pub‘写在book中
    book和author之间存在多对多关系,其关联字段‘book_auth‘写在book中
    ‘‘‘

增:
    # ********顺序为先创建被关联方,再创建关联方********
    一对一(OneToOne):
        models.Author.objects.create(name=‘alex‘)
        models.Detail.objects.create(age=38,sex=‘male‘,det_auth_id=1)  # 其中det_auth_id为关联字段,必须得写,_id是django自己加上去的(也可换成pk)
        或
        author = models.Author.objects.create(name=‘alex‘)
        models.Detail.objects.create(age=38,sex=‘male‘,det_auth=author)  # 传对象方式
    一对多(ForeignKey):#与一对一相似
    多对多(ManyToMany):
        book = models.Book.objects.filter(id=3).first()
        book.book_auth.add(1,2)  # 在给id为3的书添加了id为1和2的两个作者
        或
        book = models.Book.objects.filter(id=3).first()
        author1 = models.Author.objects.get(id=1)
        author2 = models.Author.objects.get(id=2)
        book.book_auth.add(author1,author2)  # 传对象方式

删:
    一对一and一对多:
        # ********删除被关联方字段,其所有的关联方字段都会被删除********
        models.Author.objests.filter(id=3).delete()
        models.Publisher.objests.filter(id=3).delete()
    多对多:
        book = models.Book.objects.filter(id=3)
        方式一:
            book.book_auth.clear()  # 将book下关联的所有都删掉
        方式二:
            book.book_auth.remove(1,2)  # 传id方式
            或
            author1 = models.Author.objects.get(id=1)
            author2 = models.Author.objects.get(id=2)
            book.book_auth.remove(author1,author2)  # 传对象方式

改:
    一对一and一对多:
        models.Detail.objects.update(det_auth_id=3)
        或
        author = models.Author.objects.get(id=3)
        models.Detail.objects.update(det_auth=author)  # 传对象方式
    多对多:
        book = models.Book.objects.filter(id=3)
        方式一:
            全部clear,再add
        方式二:
            book.book_auth.set([3,])  # 传id方式
            或
            author1 = models.Author.objects.get(id=1)
            author2 = models.Author.objects.get(id=2)
            book.book_auth.set(author1,author2)  # 传对象方式

查:
    # ******************基于对象的跨表查询(子查询)*********************
    ‘‘‘
        总结:
            已知谁以谁为基表进行查询
            一对一:正向查询按关联字段,反向查询按表名小写
            一对多:正向查询按关联字段,反向查询按表名小写_set.all()(因为可能查到多条数据)
            多对多:正向查询按关联字段.all(),反向查询按表名小写_set.all()(因为可能查到多条数据)
    ‘‘‘
    一对一:
        例1:查询地址为北京的人的名字
            detial = models.Detail.objects.filter(addr=‘北京‘).first()
            print(detail.det_auth.name)  # 正向查
        例2:查询alex这个人的地址
            author = models.Author.objects.filter(name=‘alex‘).first()
            print(author.detail.addr)  # 反向查
    一对多:
        例1:查询红楼梦这本书的出版社地址
            book = models.Book.objects.filter(name=‘红楼梦‘).first()
            print(book.book_pub.addr)  # 正向查
        例2:查询南京出版社出版的所有书的名字
            publisher = models.Publisher.objects.filter(name=‘南京出版社‘).first()
            books = publisher.book_set.all()  # 反向查,查到的是个queryset对象(可迭代)
            for book in books:
                print(book.name)
    多对多:
        例1:查询红楼梦这本书的所有作者
            book = models.Book.objects.filter(name=‘红楼梦‘).first()
            authors = book.book_auth.all()  # 正向查,查到的是个queryset对象(可迭代)
            for author in authors:
                print(author.name)
        例2:查询作者为alex写的所有书
            author = models.Author.objects.filter(name=‘alex‘).first()
            books = author.book_set.all()  # 反向查,查到的是个queryset对象(可迭代)
            for book in books:
                print(book.name)

    # ******************基于双下划线__的跨表查询(子查询)*********************
    ‘‘‘
        总结:
            1.基表可以是已知方,也可以是未知方,但必须相关
            2.基本上已经不区分一对一、一对多、多对多        3.本质就是用了sql中的join连表查
            3.相比于基于对象查询:没有_set.all(),也不用关联字段.all()
                优势:1.写起来比较方便,需要记得东西少             2.跨多表查询起来很方便
                劣势:查询速度较慢,查询出来的是值,而不是对象,所以不能用.的方式进行连表查
    ‘‘‘
    一对一:
        例1:查询alex这个人的地址
            -以Author表作为基表:
                ret = models.Author.objects.filter(name=‘alex‘).values(‘name‘,‘detail__addr‘)  # 反向查
                print(ret)
            -以Detail表作为基表:
                ret = models.Detail.objects.filter(det_auth__name=‘alex‘).values(‘det_auth__name‘,‘addr‘)  # 正向查
                print(ret)
        例2:查询地址为武汉的人的名字
            -以Author表作为基表:
                ret = models.Author.objects.filter(detail__addr=‘武汉‘).values(‘name‘,‘detail__addr‘)  # 反向查
                print(ret)
            -以Detail表作为基表:
                ret = models.Detail.objects.filter(addr=‘武汉‘).values(‘det_auth__name‘,‘addr‘)  # 正向查
                print(ret)
    一对多:
        例1:查红楼梦这本书的出版社地址
            -以Book作为基表:
                ret = models.Book.objects.filter(name=‘红楼梦‘).values(‘name‘,‘book_pub__addr‘)  # 正向查
                print(ret)
            -以Publisher作为基表:
                rets = models.Publisher.objects.filter(book__name=‘红楼梦‘).values(‘book__name‘,‘addr‘)  # 反向查
                print(ret)
        例2:查询南京出版社出版的所有书的名字
            -以Book作为基表:
                rets = models.Book.objects.filter(book_pub__name=‘南京出版社‘).values(‘name‘)  # 正向查
                for ret in rets:
                    print(ret)
            -以Publisher作为基表:
                rets = models.Publisher.objects.filter(name=‘南京出版社‘).values(‘book__name‘)  # 反向查
                for ret in rets:
                    print(ret)
    多对多:
        例1:查询红楼梦这本书的所有作者
            -以Book作为基表:
                rets = models.Book.objects.filter(name=‘红楼梦‘).values(‘name‘,‘book_auth__name‘)  # 正向查
                for ret in rets:
                    print(ret)
            -以Author作为基表:
                rets = models.Author.objects.filter(book__name=‘红楼梦‘).values(‘book__name‘,‘name‘)  # 反向查
                for ret in rets:
                    print(ret)
        例2:查询作者为alex写的所有书
            -以Book作为基表:
                rets = models.Book.objects.filter(book_auth__name=‘alex‘).values(‘name‘)  # 正向查
                for ret in rets:
                    print(ret)
            -以Author作为基表:
                rets = models.Author.objects.filter(name=‘alex‘).values(‘book__name‘)  # 反向查
                for ret in rets:
                    print(ret)
    终极练习(连跨多表查询):
        例:查询人民出版社出版过的所有书籍的名字及作者的姓名
            -以出版社作为基表
                rets = models.Publisher.objects.filter(name=‘人民出版社‘).values(‘book__name‘,‘book__book_auth__name‘)
            -以书作为基表
                rets = models.Book.objects.filter(book_pub=‘人民出版社‘).values(‘name‘,‘book_auth__name‘)
                print(rets)  # 打印出来是一个queryset对象中包含多个字典

原文地址:https://www.cnblogs.com/gyk1030/p/10804037.html

时间: 2024-12-11 06:12:09

Django-orm:单表查询、基于对象和双下划线的多表操作、集合查询、分组查询、F查询和Q查询的相关文章

Django Mysql数据库-基于双下划线的跨表查询

一.基于双下划线的跨表查询 Django 还提供了一种直观而高效的方式在查询(lookups)中表示关联关系,它能自动确认 SQL JOIN 联系.要做跨关系查询,就使用两个下划线来链接模型(model)间关联字段的名称,直到最终链接到你想要的 model 为止.(相当于用sql语句用join连接的方式,可以在settings里面设置,可查看sql语句) 数据库模型: class Book(models.Model): nid = models.AutoField(primary_key=Tru

模糊查询之万能的双下划线

price__gt 大于 price__lt 小于 name__contains 包含 name__icontains 也是包含,不区分大小写 Queryset 是一种数据类型,集合对象 get是实例对象的方法,update是对象集合的方法 原文地址:https://www.cnblogs.com/jintian/p/11161367.html

Django 跨表查询--神奇的双下划线和点

我在django的moles中创建了两个calss,如下: class Project(models.Model):     name = models.CharField(u'项目名称',max_length=32,blank=True)     id = models.CharField(u'项目ID',max_length=32,unique=True,primary_key=True,blank=True)     create_date = models.DateTimeField(u

django orm单表操作

orm语句 -- sql -- 调用pymysql客户端发送sql -- mysql服务端接收到指令并执行 增: 方式1: new_obj = models.UserInfo( id=2, name='小猿1', bday='2019-09-27', checked=1, ) new_obj.save() 方式2: # ret 是创建的新的记录的model对象(重点) ret = models.UserInfo.objects.create( name='小猿2', bday='2019-08-

面对对象之私有属性,以及单、双下划线 | Pythoon

# 在很多程序中会遇到__name,_name的标识符,在类中,如果属性带有双 # 下划线,表示私有属性,通俗的讲,就是不能在类命名空间外被直接调用,但是 # 可以通过方法来调用. # 其实这种表述并不明确,为什么不能被外部直接调用? # 因为,在类被定义的时候,带有双下滑线的属性,它的名字会自动发生改变: # 样式:_Classname__name # 所以,无法直接通过obj.__name访问到值;# 作用:防止子类创建的对象与基类创建的对象出现命名空间冲突的问题; # 单下划线,其实这种标

python 单下划线/双下划线使用总结(转载)

python 单下划线/双下划线使用总结 时间:2013-10-08 10:56来源:www.chengxuyuans.com Python 用下划线作为变量前缀和后缀指定特殊变量/方法. 主要存在四种情形1.    1. object # public    2. __object__ # special, python system use, user should not define like it    3. __object # private (name mangling duri

python&#160;里面的单下划线与双下划线的区别(私有和保护)

Python 用下划线作为变量前缀和后缀指定特殊变量. _xxx 不能用'from module import *'导入 ——变量名_xxx被看作是“私有 的”,在模块或类外不可以使用.__xxx__ 系统定义名字 ——__xxx 类中的私有变量名 ——只有类对象自己能访问,连子类对象也不能访问到这个数据. 核心风格:避免用下划线作为变量名的开始. 因为下划线对解释器有特殊的意义,而且是内建标识符所使用的符号,我们建议程序员避免用下划线作为变量名的开始.一般来讲,变量名_xxx被看作是“私有 的

python 里面的单下划线与双下划线的区别

python 里面的单下划线与双下划线的区别 Python 用下划线作为变量前缀和后缀指定特殊变量. _xxx 不能用'from moduleimport *'导入 __xxx__ 系统定义名字 __xxx 类中的私有变量名 核心风格:避免用下划线作为变量名的开始. 因为下划线对解释器有特殊的意义,而且是内建标识符所使用的符号,我们建议程序员避免用下 划线作为变量名的开始.一般来讲,变量名_xxx被看作是“私有 的”,在模块或类外不可以使用. 当变量是私有的时候,用_xxx 来表示变量是很好的习

python 类中的单下划线和双下划线的意义

#"单下划线" 开始的成员变量叫做保护变量,意思是只有类对象和子类对象自己能访问到这些变量: #"双下划线" 开始的是私有成员,意思是只有类对象自己能访问,连子类对象也不能访问到这个数据. class Pub(object):     var1 = 'hello'     _var2 = 'yes'     __var3 = 'hah'     def __init__(self):         self._a = 123         self.__b =