Skip to main content
 Web开发网 » 站长学院 » 浏览器插件

一篇文章带你了解Django ORM操作(基础篇)

2021年10月31日6150百度已收录

前言在日常开发中,需要大量对数据库进行增删改查操作。

如果头铁的话,使用原生SQL是最好的,毕竟性能又高,又灵活。

但是通常情况下,我们不是太需要那么苛刻的性能,也没有那么多刁钻的需求用原生SQL

通常会使用简单快捷的ORM进行增删改查

一起看学习一下Django的ORM操作吧

表结构设计还是从实际角度出发。

假设,现在我需要设计一个简单的图书管理系统,是那种买的书,不是图书馆的书!!!

我想了想,首先,肯定有一个图书表,专门存放图书的信息,最起码是这样的。

一篇文章带你了解Django ORM操作(基础篇)  Django 第1张

但是又想了想,似乎我的书想发布,肯定是需要一个出版社帮我发布的,我肯定不能自己发布所以是这样子的。

一篇文章带你了解Django ORM操作(基础篇)  Django 第2张

又想了想,书肯定是人写的,肯定要有作者,所以还需要一个作者表,应该是这样子的。

一篇文章带你了解Django ORM操作(基础篇)  Django 第3张

又想了想,这一本书如果让一般人编,难度有点大啊,一般都是多人一起完成的,所以大概还有这样一张表。

一篇文章带你了解Django ORM操作(基础篇)  Django 第4张

其实,上述漏点了一个东西,图书需要归属一个出版社的,所以,最终表结构应该是这样的!

一篇文章带你了解Django ORM操作(基础篇)  Django 第5张

Django models代码from django.db import models# 作者表class Author(models.Model): name = models.CharField(verbose_name="作者姓名", max_length=8) age = models.IntegerField(verbose_name="作者年龄") phone = models.CharField(verbose_name="作者联系方式", max_length=11)# 出版社class Publish(models.Model): title = models.CharField(verbose_name="出版社名称", max_length=16) phone = models.CharField(verbose_name="出版联系方式", max_length=11)# 图书class Book(models.Model): title = models.CharField(verbose_name="书名", max_length=32) price = models.DecimalField(verbose_name="价格", max_digits=5, decimal_places=2) PublishDate = models.DateField(verbose_name="初版日期") publish = models.ForeignKey(to=Publish, verbose_name="所属出版社", on_delete=models.CASCADE)# 图书Many作者class BookManyAuthor(models.Model): book = models.ForeignKey(to=Book, verbose_name="所属图书", on_delete=models.CASCADE) author = models.ForeignKey(to=Author, verbose_name="所属作者", on_delete=models.CASCADE)

Mysql.sql数据同上述Excel图一致!

web_author.sql

web_book.sql

web_bookmanyauthor.sql

web_publish.sql

查询操作本次采用单独使用Django ORM的方式,不需要将Django运行起来,所以也不需要写url什么的了!

前置导入import osimport django# django_orm_demo为我的项目名称os.environ.setdefault("DJANGO_SETTINGS_MODULE", "django_orm_demo.settings")django.setup# 导入models一定要在 django.setup 之后from web import models

查询所有(all)语法

models.<模型类>.objects.all例如:查询所有作者

author_list = models.Author.objects.allprint(author_list)执行结果

一篇文章带你了解Django ORM操作(基础篇)  Django 第6张

例如:查询所有图书,并且遍历详情

book_list = models.Book.objects.allfor book in book_list: print(book.title, book.price, book.PublishDate, book.publish)执行结果

一篇文章带你了解Django ORM操作(基础篇)  Django 第7张

查询指定条件(filter)语法

models.<模型类>.objects.filter(<条件>)例如:查询张三的信息

author = models.Author.objects.filter(name="张三")print(author)print(author.name)执行结果

一篇文章带你了解Django ORM操作(基础篇)  Django 第8张

似乎你发现了个错误,

'QuerySet' object has no attribute 'name'。这是因为filter(<条件>)查询出来的,可能不止一个值,就像name=张三,可能有很多张三!

所以获取的是一个列表,注意第一个红色圈圈,如果我明明知道就是一个值,也就像取第一个值,咋办?

first通过first,拿到的就是第一个值,同时也是模型类对象

代码

author = models.Author.objects.filter(name="张三").firstprint(author,type(author))print(author.name,author.phone)执行结果

一篇文章带你了解Django ORM操作(基础篇)  Django 第9张

filter支持多条件假设有俩张三

一篇文章带你了解Django ORM操作(基础篇)  Django 第10张

如果我想取第二个张三咋办?

要是能写俩条件就好了比如这样name=张三 and age=22。

注:filter后面只能跟filter或者first,filter里面的条件都是and查询

代码

# filter里面多个条件是and查询author = models.Author.objects.filter(name="张三",age=22).firstprint(author,type(author))print(author.name,author.phone)执行结果

一篇文章带你了解Django ORM操作(基础篇)  Django 第11张

常用filter条件列表熟悉Mysql的可能都知道,有=,<,<=,like等各种范围查询,同样,Django也同样支持!

filter通过__来构造条件

# 包含三字段__contains="三" # 原生SQL条件:where 字段 like "%三%"# 以三开头字段__startswith="三" # 原生SQL条件:where 字段 like "三%"# 以三结尾字段__startswith="三" # 原生SQL条件:where 字段 like "%三"# 为空字段__is=True # 原生SQL条件:where 字段 IS # 不为空字段__is=False # 原生SQL条件:where 字段 IS NOT # in字段__in=[1,2,3] # 原生SQL条件:where 字段 IN (1, 2, 3)# >字段__gt=1 # 原生SQL条件:where 字段 > 1# >=字段__gte=1 # 原生SQL条件:where 字段 >= 1# <字段__lt=1 # 原生SQL条件:where 字段 < 1# <=字段__lte=1 # 原生SQL条件:where 字段 <= 1# 日期字段,年日期字段__year=2020 # 原生SQL条件:where 日期字段 BETWEEN 2020-01-01 AND 2020-12-31# 日期字段,月日期字段__month=3 # 原生SQL条件:where EXTRACT(MONTH FROM 表名.日期字段) = 3# 日期字段,天日期字段__day=4 # 原生SQL条件:where EXTRACT(DAY FROM 表名.日期字段) = 4# 时间比大小,|为或的意思日期字段__gt|lt|...="2020-10-10" # 原生SQL条件:where 日期字段 > 2020-10-10# 比大小还可以是时间类型import datetime日期字段__gt|lt|...=datetime.date(2020,10,10)# 同上# 时间范围筛选日期字段__range=("2020-01-01","2020-06-01") # 原生SQL条件:where 时间字段 BETWEEN 2020-01-01 AND 2020-06-01日期字段__range=(datetime.date(2020,1,1),datetime.date(2020,6,1)) # 同上

get其实当我们只需要获取一个值时,还可以使用get。

代码

author = models.Author.objects.get(name="李四")print(author,type(author))print(author.name,author.phone)执行结果

一篇文章带你了解Django ORM操作(基础篇)  Django 第12张

但是这个get不太推荐使用,原因如下

如果get条件获取了俩或俩以上的值,会报错。

如果get条件获取不到值,还是会报错。

示例代码

author = models.Author.objects.get(name="张三")# error:get returned more than one Author -- it returned 2!author = models.Author.objects.get(name="不存在")# error:Author matching query does not exist.author = models.Author.objects.filter(name="不存在").first# 结果:None所以,推荐使用filter,如果确定只有一条,那就filter.first,如果需要多条,遍历即可!

query在某些特殊情况下,我们可能对于查询的结果感到有些意外!

可能需要看看原生SQL是啥,这时候需要用到query。

注:query只能用在filter后面。

代码

sql = models.Author.objects.filter(name="李四").queryprint(sql)执行结果

一篇文章带你了解Django ORM操作(基础篇)  Django 第13张

总结本篇通过一个类似实际的需求,进行了一个表结构设计。

有书表,出版社表,作者表,图书和作者多对多表。

以这几张表为例,进行Django ORM的学习。

学习了如何查询所有,如何条件查询,filter常用条件有哪些。

get和filter.first区别,如何通过query进行查看原生SQL。

如果在操作过程中有任何问题,记得下面留言,我们看到会第一时间解决问题。

用微笑告诉别人,今天的我比昨天强,今后也一样。

如果你觉得文章还可以,记得点赞留言支持我们哈。感谢你的阅读,有问题请记得在下方留言噢~

福利

入门Python的最强三件套《ThinkPython》、《简明Python教程》、《Python进阶》的PDF电子版已打包提供给大家,「P3」即可获取。

评论列表暂无评论
发表评论
微信