目录

一、orm查询

1.1配置测试脚本

为了方便我们测试SQL语句,我们需要配置一下tests.py文件,在这里测试我们的SQL语句,单独测试Django中的py文件都可以这样配置。

第一种方式:

import os

if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite1.settings") import django django.setup() # 一定要等待测试脚本搭建完毕之后 才能导入django文件进行测试
from app01 import models

第二种方法:

直接新建一个名称任意的py文件,在里面写上上面的配置

1.1.1Django终端打印SQL语句的配置

在settings里面随便找个地方复制下面的代码即可在终端看到orm向数据库发送的SQL语句。

LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console':{
'level':'DEBUG',
'class':'logging.StreamHandler',
},
},
'loggers': {
'django.db.backends': {
'handlers': ['console'],
'propagate': True,
'level':'DEBUG',
},
}
}

1.2单表操作

1.2.1创建数据

创建数据就是给数据库中的表添加记录,这里有两种添加记录的方法。

create方法

publish_obj = models.Publisher.objects.create(publisher_name='湖南文艺出版社',address='湖南省')
print(publish_obj)

利用对象的绑定方法

   publish_obj = models.Publisher(publisher_name='机械工业出版社',address='北京')
publish_obj.save()

1.2.2修改数据

利用queryset方法

说明:pk会自动帮我们找到当前表的主键字段,以后我们都用pk指代主键字段。

filter查询出来的结果是一个queryset对象,queryset对象有以下两个特点:

1.可以无限制的调用queryset的方法

2.可以对象点query的方法查看当前结果内部对应的SQL语句

res = models.Publisher.objects.filter(pk=1).update(address='西安')

利用对象

res = models.Publisher.objects.filter(pk=1).update(address='西安')
publisher_obj = models.Publisher.objects.get(pk=1)#get查找对象如果找不到会报错
publisher_obj.address = '湖南'
publisher_obj.save()

get和filter的区别

filter获取到的是一个queryset对象,类似于一个列表,如果对象为空时,就如同一个空列表;get获取到的是对象本身,如果对象不存在会报错,所以不推荐使用。

1.2.3删除数据

利用queryset方法

models.Publisher.objects.filter(pk=2).delete()

利用对象

publish_obj = models.Publisher.objects.get(pk=3)
publish_obj.delete()

1.2.4查询数据

queryset的filter()和对象的get()都是对数据的查询方法,括号内的条件相当于SQL语句中where后面的部分,这里各个条件是and关系。

获取一条记录对象

filter()获取到的是一个queryset对象,获取真正的对象可以使用first()和last()方法具体使用如下:

res = models.Publisher.objects.filter(pk=1).first()
res1 = models.Publisher.objects.filter(pk=1).last()
#会获取到查找到的第一个对象、最后一个对象

1.2.5计数

count()按照传入括号的条件统计符合该条件的所有的记录的个数。

1.2.6values()

values()获取数据对象中指定的字段的值,可以有多个,这里以queryset对象列表套字典的形式返回。

res3 = models.Publisher.objects.values('publisher_name','address')
print(res3,num)
# < QuerySet[{'publisher_name': '湖南文艺出版社', 'address': '湖南'}, {'publisher_name': '湖南文艺出版社', 'address': '湖南省'}, {
# 'publisher_name': '湖南文艺出版社', 'address': '湖南省'}] > 3

1.2.7vlaues_list()

获取数据对象中指定的字段的值,可以有多个,这里以queryset对象列表套元组的形式返回。

res4 = models.Publisher.objects.values_list('publisher_name','address')
print(res4)
# < QuerySet[('湖南文艺出版社', '湖南'), ('湖南文艺出版社', '湖南省'), ('湖南文艺出版社', '湖南省')] >

1.2.8order_by()

按照指定的字段排序,默认是升序,如果降序则需在字段名前加负号,返回的是queryset对象。

res5 = models.Publisher.objects.order_by('-id')
print(res5)
# < QuerySet[ < Publisher: Publisher
# object >, < Publisher: Publisher
# object >, < Publisher: Publisher
# object >] >

1.2.9reverse()

逆序排序,这里必须是已经经过order_by()排序的对象,否则无法达到期望的排序目的。

1.2.10exclude()

exclude('xxx')查出排除xxx之后的内容,得到的是queryset对象

res6 = models.Publisher.objects.exclude(pk=5)
# < QuerySet[ < Publisher: Publisher
# object >, < Publisher: Publisher
# object >] > res7 = models.Publisher.objects.values('address').exclude(address='湖南')
print(res7)
<QuerySet [{'address': '湖南省'}, {'address': '湖南省'}]>

1.2.11exists()

判断查询的结果是否有值,返回一个bool值,该方法其实并不实用因为数据本身自带bool值。

res7 = models.Publisher.objects.values('address').exists()
print(res7)
#True

1.2.12distinct()

对查询到的结果按照查询的条件进行去重,如果查询条件是自增id则无法去重。

res7 = models.Publisher.objects.values('address').distinct()
print(res7)
<QuerySet [{'address': '湖南'}, {'address': '湖南省'}]>

1.3双下划线查询

双下划线查询可以进行范围查询:

  • 范围查询__gt大于、__lt小于、__gte大于等于、__lte小于等于、、

    说明:python对数据不敏感,所以数据是小数的时候小于等于大于等于不一定能够取到等于的数据

    res8 = models.Publisher.objects.filter(id__gt=2)
    print(res8)
    #<QuerySet [<Publisher: Publisher object>, <Publisher: Publisher object>]>
  • __in条件或查询

    查询条件是__in等于的几个条件,这几个条件是或的关系。

    res8 = models.Publisher.objects.filter(id__in=[1,2,3])
    print(res8)
    #<QuerySet [<Publisher: Publisher object>]>
  • 区间查询__range这是一个闭区间查询

    res8 = models.Publisher.objects.filter(id__range=(1,3))
    print(res8)
    #<QuerySet [<Publisher: Publisher object>]>
  • __year按年份查

    res = models.Books.objects.filter(publish_date__year='2019')
  • __month按月查

    res = models.Books.objects.filter(publish_date__month='1')
  • 模糊查询__startwith、__endwith、__contains默认识别字母的大小写、__icontains忽略大小写

    查询出以XXX开头,以XXX结尾,内容中有XXX,内容中有XXX的对象且忽略字母大小写(__icontains)。

    res8 = models.Publisher.objects.filter(address__iendswith='南')
    print(res8) res8 = models.Publisher.objects.filter(address__icontains='南')
    print(res8)
    #<QuerySet [<Publisher: Publisher object>, <Publisher: Publisher object>, <Publisher: Publisher object>]>

1.4一对多字段数据的增删改查

增加一条记录

方式一:直接给表里面的实际字段和主键值
models.Book.objects.create(name='三体',price=100,publisher_id=1) 方式二:传虚拟字段和数据对象
publish_obj = models.Publisher.objects.filter(pk=1).first()
models.Book.objects.create(name='乡村教师',price=10,publisher=publish_obj)#这里的publisher是出版社表的表名

更改一条记录

方式一:直接更改
models.Book.objects.filter(pk=5).update(publisher_id=4) 方式二:传虚拟字段和数据对象
publisher_obj = models.Publisher.objects.filter(pk=4).first()
models.Book.objects.filter(pk=5).update(publisher=publisher_obj)

删除一条记录

models.Book.objects.filter(pk=5).delete()#默认是级联删除级联更新,就是这张表删除了与之有外键关系的表也会跟着变化

1.5多对多字段数据的增删改查

1.5.1在第三张表中添加一条记录

方式一:
book_obj = models.Book.objects.filter(pk=6).first()
book_obj.author.add(1,2)#在第三张表中给书籍绑定主键为1和主键为2的作家
book_obj.author.add(1)#在第三张表中给书籍绑定主键为1的作家 方式二:
book_obj = models.Book.objects.filter(pk=6).first()
# book_obj.author.add(1,2)
author_obj1 = models.Author.objects.filter(pk=1).first()
author_obj2 = models.Author.objects.filter(pk=2).first()
book_obj.author.add(author_obj1,author_obj2)
"""
add方法能够朝第三张关系表添加数据,支持传数字,如:add(1,2)
也支持传对象,如:add(author_obj,author_obj1)
并且两者都可以传多个
"""

1.5.2在第三张表中修改一条记录

方式一:
book_obj = models.Book.objects.filter(pk=6).first()
book_obj.author.set((1,2)) 方式二:
author_obj1 = models.Author.objects.filter(pk=1).first()
author_obj2 = models.Author.objects.filter(pk=3).first()
# book_obj.author.set(author_obj1, author_obj2)
#TypeError: set() takes 2 positional arguments but 3 were given
book_obj.author.set((author_obj1, author_obj2))#需要说明的是括号内传入的是可迭代对象,否则会报上面的错误 """
set修改多对多关系表中的数,可以传数字也可以传对象(需要注意的是括号内必须是可迭代对象)并且都支持传多个。
set((1,3))
set((author_obj,author_obj1))
"""

1.5.3在第三张表中删除一条记录

方式一:
book_obj = models.Book.objects.filter(pk=6).first()
book_obj.author.remove(1, 2) 方式二:
author_obj1 = models.Author.objects.filter(pk=1).first()
author_obj2 = models.Author.objects.filter(pk=3).first()
book_obj.author.remove(author_obj1, author_obj2)
"""
remove可以传数字也可以穿对象并且都支持传多个,且不需要迭代。如果传入的对象或者数字是表中根本不存在的,不会报错,只是不执行删除语句而已。
remove(1,2)
remove(author_obj,author_obj1)
"""

1.5.4清空第三张表中指定的所有记录

book_obj = models.Book.objects.filter(pk=2).first()
book_obj.authors.clear()
#清空指定的书籍在第三张表中的所有记录

1.6跨表查询

1.6.1正反向查询

正反向查询:外键在书那里,由书查出版社就是正向,由出版社查书就是反向查询

正向查询按字段,反向查询按表名小写 + _set。

1.6.2基于对象的跨表查询

一起来看下面的例子

1.查询书籍主键为7的出版社名称

    book_obj = models.Book.objects.filter(pk=7).first()
print(book_obj.publisher)#出版社对象
print(book_obj.publisher.publisher_name)
#Publisher object
#人民文学出版社

2.查询书籍主键为6的作者姓名

book_obj = models.Book.objects.filter(pk=6).first()
print(book_obj.author)#app01.Author.None
print(book_obj.author.all())
#<QuerySet [<Author: Author object>, <Author: Author object>]>
print(book_obj.author.all().first().auth_name,book_obj.author.all().last().auth_name)
#刘同 大冰

从上面两题可以看出,基于对象跨表查询以书为例,当一本书有一个作者时不需要用all()方法,且得到的就是作者对象,当一本书有多个作者时需要用all()方法,且得到的是QuerySet列表。

3.查询湖南文艺出版社出版过的书籍

    publisher_obj = models.Publisher.objects.filter(publisher_name='湖南文艺出版社').first()
print(publisher_obj.book_set)#app01.Book.None
print(publisher_obj.book_set.all())
#<QuerySet [<Book: Book object>, <Book: Book object>, <Book: Book object>]>

4.查询作者刘同的详细介绍

author_obj = models.Author.objects.filter(name='刘同').first()
print(author_obj.author_detail)#这里已经是author_detail表的一条记录(对象)
print(author_obj.author_detail.info)

5.查询刘同写过的书

author_obj = models.Author.objects.filter(auth_name='刘同').first()
print(author_obj.book_set)#app01.Book.None
print(author_obj.book_set.all())
#<QuerySet [<Book: Book object>, <Book: Book object>, <Book: Book object>]>

6.查询作者信息是‘著名科幻作家’的作者姓名

author_detail_obj = models.AuthorDetail.objects.filter(info='著名科幻作家').first()
print(author_detail_obj.author)
print(author_detail_obj.author.auth_name)

反向查询的时候需要表名小写+_set的情况:一对多,多对多;一对一的情况不需要加_set,因为两张表是一一对应的关系。

1.6.3基于双下划线的跨表查询

1.查询书籍的id为6的出版社的名称

正向查询

res = models.Book.objects.filter(pk=6).values('publisher__publisher_name')
print(res)#<QuerySet [{'publisher__publisher_name': '大象出版社'}]>
#表名加双下划线就就进入了这张表,后面可以直接跟字段名称

反向查询

res = models.Publisher.objects.filter(book__pk=6).values('publisher_name')
print(res)
#<QuerySet [{'publisher_name': '大象出版社'}]>

2.查询书籍id是6的作者姓名和简介

正向查询
res = models.Book.objects.filter(pk=6).values('author__auth_name','author__detail')
print(res)
#<QuerySet [{'author__auth_name': '刘同', 'author__detail': '知名作家'}, {'author__auth_name': '大冰', 'author__detail': '知名作家,旅行家,歌手'}]> 反向查询
res1 = models.Author.objects.filter(book__pk=6).values('auth_name','detail')
print(res1)
#<QuerySet [{'auth_name': '刘同', 'detail': '知名作家'}, {'auth_name': '大冰', 'detail': '知名作家,旅行家,歌手'}]>

3.查询大象出版社出版过的书籍

正向查询:
res = models.Publisher.objects.filter(publisher_name='大象出版社').values('book__name')
print(res)#<QuerySet [{'book__name': '乖,摸摸头'}]> 反向查询:
res1 = models.Book.objects.filter(publisher__publisher_name='大象出版社').values('name')
print(res1)#<QuerySet [{'name': '乖,摸摸头'}]>

Django orm(1)的更多相关文章

  1. 【python】-- Django ORM(进阶)

    Django ORM(进阶) 上一篇博文简述了Django ORM的单表操作,在本篇博文中主要简述Django ORM的连表操作. 一.一对多:models.ForeignKey() 应用场景:当一张 ...

  2. 【python】-- Django ORM(基础)

    Django ORM(基础) Django 框架十分强大,自带数据库操作功能.Django 跟 SQLAchemy 一样,也是通过ORM(Object Relational Mapping,关系对象映 ...

  3. Part 5 - Django ORM(17-20)

    https://github.com/sibtc/django-beginners-guide/tree/v0.5-lw from django.conf.urls import url from d ...

  4. pycharm平台下的Django教程(转)

    本文面向:有python基础,刚接触web框架的初学者. 环境:windows7   python3.5.1  pycharm专业版  Django 1.10版 pip3 一.Django简介 百度百 ...

  5. 【笔记】Django基础(一)

    ---恢复内容开始--- [笔记]Django基础(一) oldboy Django  一 关于Python框架的本质 1. HTTP协议消息的格式: 请求(request) 请求方法 路径 HTTP ...

  6. Django系列(一):前期准备

    1.web应用 Web应用程序是一种可以通过web访问的应用程序,程序的最大好处是用户很容易访问应用程序,用户只需要有浏览器即可,不需要再安装其他软件.应用程序有两种模式C/S.B/S.C/S是客户端 ...

  7. 【ASP.NET程序员福利】打造一款人见人爱的ORM(二)

    上一篇我已经给大家介绍AntORM的框架[ASP.NET程序员福利]打造一款人见人爱的ORM(一),今天就来着重介绍一下如何使用这套框架 1>AntORM 所有成员 如果你只想操作一种数据库,可 ...

  8. 自己开发轻量级ORM(一)

    在开发ORM之前,先简单的介绍下ORM的基本概念. 对象关系映射(Object Relational Mapping,简称ORM)是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术. 简单的 ...

  9. Django学习(2)数据宝库

    数据库是一所大宝库,藏着各种宝贝.一个没有数据库的网站,功能有限.在Django中,支持的数据库有以下四种: SQLite3 MySQL PostgreSQL Oracle 其中SQLite3为Dja ...

随机推荐

  1. 远程桌面 使用 本地输入法(虚拟化 终端 远程接入 RemoteApp)

    远程桌面连接组件是微软从Windows 2000 Server开始提供的,该组件一经推出便受到了很多用户的拥护和使用.   在WINDOWS XP和WINDOWS SERVER 2003中微软公司将该 ...

  2. Failure to find com.oracle:ojdbc6:jar:11.2.0.1.0

    报错原因:oracle的ojdbc.jar是收费的,maven的中央仓库是没有的,需要下载到本地,然后打包进maven仓库 1.下载ojdbc6-11.2.0.1.0.jar包 http://cent ...

  3. Java ——继承

    本节重点思维导图 面向对象三大特性:封装.继承.多态 面向对象编程的第一原则:面向接口编程 继承 代码利用的方式,子类与父类之间的关系 语法 访问控制修饰符 class 类名 extends父类名{ ...

  4. Java多线程学习——sleep和yield

    Thread.sleep(); Thread.yield(); 相同点: 让线程暂停运行. 都是静态方法,可以直接调用. 不同点: sleep让线程从运行状态进入阻塞状态,但是不放开手中的资源. yi ...

  5. Snow的追寻--线段树维护树的直径

    Snow终于得知母亲是谁,他现在要出发寻找母亲.王国中的路由于某种特殊原因,成为了一棵有n个节点的根节点为1的树,但由于"Birds are everywhere.",他得到了种种 ...

  6. 【Linux开发】如何查看Linux kernel的内置模块驱动列表和进程ID

    [Linux开发]如何查看Linux kernel的内置模块驱动列表和进程ID 标签:[Linux开发] 命令: cat /lib/modules/$(uname -r)/modules.builti ...

  7. java中Map的put函数和get函数用法

    ---内容开始--- 没有比较完整的说明他们的用法,一般就只能看源函数,但是看起来比较的费劲. 那么究竟put函数和get函数的用法是如何的呢? 当然java中的Map集合是有Key和Value的. ...

  8. 逆向工程 生成mapper 接口的 重要方法

    @Test public void testSelectByExample() { ItemsExample itemsExample = new ItemsExample(); ItemsExamp ...

  9. POJ 3135 Polygons on the Grid(枚举+凸包)

    题目大意是让你用这n条边放在网格上构成凸包,并且边的两端点必须在网格上. 那么比较容易想到的就是枚举可能情况,因为这样的勾股数组成情况不多,因此可以直接枚举所有连出去的边反映在坐标轴上的所有情况,最后 ...

  10. CSRF Failed: CSRF token missing or incorrect

    Django设置本身没有关闭CSRF Django设置已经关闭CSRF,可能是由于两个项目都使用同一个端口,调试的时候就会出现Cookie里面csrftoken重用的问题,清理Cookie就好