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

Karen110
• 阅读 1379

前言

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

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

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

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

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

表结构设计

还是从实际角度出发。

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

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

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

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

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

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

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

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

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

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

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

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 os
import 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.all()
print(author_list)

执行结果

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

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


book_list = models.Book.objects.all()
for book in book_list:
    print(book.title, book.price, book.PublishDate, book.publish)

执行结果

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

查询指定条件(filter)

语法

models.<模型类>.objects.filter(<条件>)

例如:查询张三的信息


author = models.Author.objects.filter(name="张三")
print(author)
print(author.name)

执行结果

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

似乎你发现了个错误,'QuerySet' object has no attribute 'name'

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

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

first

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

代码

author = models.Author.objects.filter(name="张三").first()
print(author,type(author))
print(author.name,author.phone)

执行结果

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

filter支持多条件

假设有俩张三

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

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

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

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

代码


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

执行结果

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

常用filter条件列表

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

filter通过__来构造条件


# 包含三
字段__contains="三" # 原生SQL条件:where 字段 like "%三%"
# 以三开头
字段__startswith="三" # 原生SQL条件:where 字段 like "三%"
# 以三结尾
字段__startswith="三" # 原生SQL条件:where 字段 like "%三"
# 为空
字段__isnull=True # 原生SQL条件:where 字段 IS NULL
# 不为空
字段__isnull=False # 原生SQL条件:where 字段 IS NOT NULL
# 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操作(基础篇)

但是这个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="李四").query
print(sql)

执行结果

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

总结


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

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

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

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

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

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

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

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

想学习更多关于Python的知识,可以参考学习网址:http://pdcfighting.com/,点击阅读原文,可以直达噢~

**-----**------**-----**---**** End **-----**--------**-----**-****

往期精彩文章推荐:

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

欢迎各位大佬点击链接加入群聊【helloworld开发者社区】:https://jq.qq.com/?_wv=1027&k=mBlk6nzX进群交流IT技术热点。

本文转自 https://mp.weixin.qq.com/s/L8Uumq3apFi0nohqvfqINA,如有侵权,请联系删除。

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Karen110 Karen110
3年前
​一篇文章总结一下Python库中关于时间的常见操作
前言本次来总结一下关于Python时间的相关操作,有一个有趣的问题。如果你的业务用不到时间相关的操作,你的业务基本上会一直用不到。但是如果你的业务一旦用到了时间操作,你就会发现,淦,到处都是时间操作。。。所以思来想去,还是总结一下吧,本次会采用类型注解方式。time包importtime时间戳从1970年1月1日00:00:00标准时区诞生到现在
Stella981 Stella981
3年前
Python3:sqlalchemy对mysql数据库操作,非sql语句
Python3:sqlalchemy对mysql数据库操作,非sql语句python3authorlizmdatetime2018020110:00:00coding:utf8'''
Easter79 Easter79
3年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
为什么mysql不推荐使用雪花ID作为主键
作者:毛辰飞背景在mysql中设计表的时候,mysql官方推荐不要使用uuid或者不连续不重复的雪花id(long形且唯一),而是推荐连续自增的主键id,官方的推荐是auto_increment,那么为什么不建议采用uuid,使用uuid究
Python进阶者 Python进阶者
10个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这