Python Django ORM 的工作原理

news2024/11/25 22:29:08

在 Web 开发中,处理数据库是非常常见的需求,尤其是在构建动态应用程序时。Django 作为一个流行的 Python Web 框架,提供了一套强大的工具帮助开发者轻松管理数据库。Django 的 ORM(对象关系映射,Object-Relational Mapping)就是其中的重要组成部分,它使开发者可以通过 Python 代码与数据库进行交互,而无需编写 SQL 语句。对于新手来说,理解 Django ORM 的工作原理将极大地简化数据库操作。

本文将深入解释 Django ORM 的基本原理,并通过具体的代码示例帮助你更好地理解如何使用它。

在这里插入图片描述

什么是 ORM?

在正式介绍 Django ORM 之前,首先了解一下 ORM 的基本概念。ORM(Object-Relational Mapping,对象关系映射)是一种将面向对象编程语言中的对象与关系型数据库中的表进行映射的技术。简单来说,它允许你在代码中通过对象操作数据库,而不是通过 SQL 语句。

ORM 的工作机制是通过将数据库表映射到模型类(Model),每个类的实例代表数据库中的一条记录。通过 ORM,你可以像操作 Python 对象一样操作数据库中的数据,这大大减少了学习 SQL 和写复杂查询的需求。

Django ORM 是 Django 框架内置的 ORM 系统,它通过模型类定义数据库结构,并允许你通过 Python 代码与数据库进行交互。接下来,我们将详细介绍 Django ORM 的工作流程。

Django ORM 的基本工作原理

在 Django 中,ORM 的主要职责是将 Python 对象与数据库表相关联。这包括以下几个核心步骤:

  1. 定义模型类:每个模型类都映射到数据库中的一张表,类的属性对应于表中的字段。
  2. 迁移数据库结构:Django 提供了迁移(migrations)机制,它可以将模型类的结构变化反映到数据库中,自动生成 SQL 语句并执行。
  3. 操作数据库:通过 Django ORM,开发者可以通过 Python 代码执行 CRUD 操作(创建、读取、更新和删除),而无需直接编写 SQL 语句。
  4. 查询优化和链式查询:ORM 提供了高效的查询工具,可以通过链式调用构建复杂的查询逻辑,并保证执行效率。

1. 定义模型类

在 Django 中,每个模型类都代表数据库中的一张表。要定义一个模型类,我们需要在应用的 models.py 文件中创建一个继承自 models.Model 的类。

例如,假设我们正在开发一个博客应用,需要一个用于存储文章的表。可以定义如下的模型类:

from django.db import models

class Post(models.Model):
    title = models.CharField(max_length=200)
    content = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def __str__(self):
        return self.title

在这个示例中,我们定义了一个 Post 类,表示博客文章。这个类有以下几个字段:

  • title: 文章标题,使用 CharField,表示一个字符串字段,max_length=200 限制了字符长度。
  • content: 文章内容,使用 TextField,用于存储大量文本。
  • created_at: 文章创建的时间,使用 DateTimeField,并且设置了 auto_now_add=True,表示自动填充当前时间。
  • updated_at: 文章更新时间,使用 DateTimeField,并设置 auto_now=True,每次文章更新时会自动修改这个字段。

每个字段类型(CharFieldTextFieldDateTimeField 等)都对应数据库中的数据类型,Django ORM 会根据这些定义生成相应的 SQL 语句。

2. 创建数据库迁移

模型类定义好之后,接下来需要将这些变化应用到数据库中。这是通过 Django 的迁移系统完成的。迁移是 ORM 用来跟踪和管理数据库表结构变化的工具,它可以自动生成 SQL 语句并应用到数据库。

执行以下命令来创建迁移文件:

python manage.py makemigrations

这个命令会扫描模型的变化,并生成相应的迁移文件。这些文件包含了创建或修改数据库表的 SQL 语句。接着,运行以下命令来应用迁移并将这些变化同步到数据库:

python manage.py migrate

当你运行 migrate 命令时,Django 会根据迁移文件生成 SQL 语句并执行,从而在数据库中创建或修改相应的表。

3. 操作数据库

当模型和数据库同步好之后,我们可以通过 Django ORM 来操作数据库了。Django ORM 提供了一些方便的方法来执行 CRUD(创建、读取、更新、删除)操作。

1. 创建数据

你可以通过模型类创建数据库记录。以下是创建一条新的博客文章的示例:

from blog.models import Post

# 创建一篇新的文章
new_post = Post(title="我的第一篇文章", content="这是我的第一篇博客文章的内容。")
new_post.save()  # 保存到数据库

在上面的代码中,我们首先实例化了 Post 类,传入文章的标题和内容。调用 save() 方法后,Django ORM 会生成一个 INSERT 语句,并将数据写入到数据库中。

2. 查询数据

Django ORM 提供了强大的查询功能,你可以使用 Post.objects 来查询 Post 表中的数据。

  • 查询所有记录
posts = Post.objects.all()  # 返回所有文章对象的列表
  • 按条件查询
post = Post.objects.get(id=1)  # 根据主键 id 查询单条记录
  • 过滤查询
recent_posts = Post.objects.filter(created_at__year=2024)  # 查询 2024 年发布的文章

在这里,filter() 方法返回一个满足条件的查询集(QuerySet)。Django 的查询集支持链式调用,你可以通过多个条件组合成复杂的查询。

3. 更新数据

要更新一条记录,首先需要先查询出该记录,然后修改字段并调用 save() 方法。

post = Post.objects.get(id=1)
post.title = "更新后的标题"
post.save()  # 保存更改

Django ORM 会生成一个 UPDATE 语句,将修改后的数据更新到数据库。

4. 删除数据

要删除一条记录,你可以使用 delete() 方法:

post = Post.objects.get(id=1)
post.delete()  # 删除这条记录

delete() 方法会生成 DELETE 语句,并从数据库中删除该记录。

4. 查询优化与链式查询

Django ORM 的查询集是惰性执行的,这意味着查询操作不会立即访问数据库,只有当需要访问结果时才会执行 SQL 查询。这种惰性执行机制提高了性能,因为它允许 Django 构建复杂的查询链,而无需在每一步都访问数据库。

1. 链式查询

你可以通过链式调用将多个查询条件组合起来。以下是一个示例:

posts = Post.objects.filter(title__contains="Django").filter(created_at__year=2024)

在这个示例中,filter() 方法被调用了两次,最终的 SQL 查询将包含两个条件,查询标题中包含 “Django” 且在 2024 年创建的文章。

2. 查询优化

Django ORM 还提供了查询优化工具,例如 select_related()prefetch_related(),用于优化涉及外键和多对多关系的查询。

  • select_related():用于减少外键查询的数据库访问次数。它通过一个 JOIN 操作一次性获取相关表的数据。
posts = Post.objects.select_related('author').all()  # 假设 Post 表有一个外键指向 Author 表
  • prefetch_related():用于处理多对多关系的查询优化。它通过执行两次独立查询来减少数据库访问次数。
posts = Post.objects.prefetch_related('tags').all()  # 假设 Post 表有一个多对多的 tags 关系

通过这些查询优化工具,你可以显著提高数据库查询的效率,尤其在处理大型项目或复杂的数据库结构时。

Django ORM 的高级功能

除了基本的 CRUD 操作,Django ORM 还提供了一些高级功能,帮助开发者更灵活地与数据库进行交互。

1. 模型继承

Django 支持模型继承,这意味着你可以创建一个基类模型,并让其他模型从它继承字段和方法。以下是一个示例:

class BaseModel(models.Model):
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        abstract = True  # 抽象基类,不会生成表



class Post(BaseModel):
    title = models.CharField(max_length=200)
    content = models.TextField()

在这个示例中,BaseModel 是一个抽象基类,它定义了 created_atupdated_at 字段。Post 类继承了这个基类,并自动拥有这两个字段。

2. 自定义管理器

Django ORM 允许你创建自定义管理器(Manager)来扩展查询集的功能。例如,假设我们想创建一个自定义查询集,只返回最近发布的文章,可以这样实现:

class PostManager(models.Manager):
    def recent_posts(self):
        return self.filter(created_at__gte=datetime.now()-timedelta(days=30))

class Post(models.Model):
    title = models.CharField(max_length=200)
    content = models.TextField()

    objects = PostManager()  # 使用自定义管理器

现在我们可以调用 Post.objects.recent_posts() 来获取最近 30 天内发布的文章。

结论

Django ORM 提供了强大而灵活的工具,帮助开发者通过 Python 代码与数据库交互。它将面向对象编程的理念引入到数据库操作中,大大减少了编写 SQL 的需求,简化了 Web 开发中的数据库管理工作。通过本文的介绍,你应该能够理解 Django ORM 的基本原理,并开始在项目中使用它进行数据库操作。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2202148.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【STM32单片机_(HAL库)】4-5-2【定时器TIM】【感应开关盖垃圾桶】HC-SR04超声波模块实验

1.硬件 STM32单片机最小系统HC-SR04超声波模块 2.软件 hcsr04驱动文件添加main.c程序 #include "sys.h" #include "delay.h" #include "led.h" #include "uart1.h" #include "hcsr04.h"int main(void) {HAL_Init(); …

k8s微服务

一 、什么是微服务 用控制器来完成集群的工作负载,那么应用如何暴漏出去?需要通过微服务暴漏出去后才能被访问 Service是一组提供相同服务的Pod对外开放的接口。 借助Service,应用可以实现服务发现和负载均衡。 service默认只支持4层负载均…

全网首创Windows Powershell 批量创建、重命名和拷贝文件夹和文件到指定目录

哈喽大家好,欢迎来到虚拟化时代君(XNHCYL)。 “ 大家好,我是虚拟化时代君,一位潜心于互联网的技术宅男。这里每天为你分享各种你感兴趣的技术、教程、软件、资源、福利…(每天更新不间断,福利…

Redis 完整指南:命令与原理详解

目录 1. Redis 概述什么是 RedisRedis 应用场景 2. 安装与启动Redis 安装步骤源代码安装使用包管理器安装(以 Ubuntu 为例) 编译与启动命令编客户端连接 3. Redis 存储结构KV 存储结构数据结构类型String(字符串)List(…

selenium有多个frame页时的操作方法(5)

之前文章我们提到,在webdriver.WebDriver类有一个switch_to方法,通过switch_to.frame()可以切换到不同的frame页然后才再定位某个元素做一些输入/点击等操作。 比如下面这个测试网站有2个frame页:http://www.sahitest.com/demo/framesTest.h…

支付宝开放平台-开发者社区——AI 日报「10 月 10 日」

1 AI逆向绘画火了!一键重绘梵高《星空》,来自华盛顿大学 量子位|阅读原文 这项魔法来自华盛顿大学,项目名为Inverse Painting,相关论文已入选SIGGRAPH Asia 2024,其中两位作者还是东北大学(Bo…

车载SerDes历史和发展概述

1. 场景起源 1.1 原始时代: 在古老的很久很久以前,摄像头和显示屏等接口是多种多样的,丰富多彩的。大家各凭本事,各显神通,在各种地盘上成立各种帮派。比如CVBS、DVP、AHD、USB。 CVBS,包括后面的AHD&a…

【puppeteer】wvp-puppeteer制作 过程

、 制作 docker build -t dxw-pupet4 -f .\dockerfile2 . docker run -itd --name dxw4 -p 35105:35105 dxw-pupet4 推送到私库 docker tag dxw-pupet4:latest dualvenregistry:5000/wvp-puppeteer:v1.0 docker push dualvenregistry:5000/wvp-puppeteer:v1.0 重启桌面上…

2024.10.9 QT事件

1.思维导图 2.一个圆形根据wsad上下左右移动&#xff0c;超出界限则不移动。鼠标点击和双击事件测试。 1.main.cpp #include "mainwindow.h"#include <QApplication>int main(int argc, char *argv[]) {QApplication a(argc, argv);MainWindow w;w.show();re…

JAVA《接口》

文章目录 一、接口是什么&#xff1f;1.1 接口的概念1.2 接口与类的相似点和区别1.3 接口的特性 二、接口的使用2.1 接口的实现2.2 实现多个接口2.3 接口之间的扩展(继承) 三、接口的使用实例3.1 Comparable接口3.2 Comparator接口3.3 Clonable接口3.3.1 使用Clonable接口3.3.2…

Linux——cp-mv-rm命令

cp命令 复制文件 cp test01.txt test02.txt 复制文件夹 cp -r hsy01 hsy02 mv命令 移动文件/文件夹 rm命令 删除文件 rm test.txt 删除文件夹&#xff08;目录 rm -r hsy01 通配符 * 匹配任意内容 注意* 位置 强制删除-f root超级管理员

数字化转型的深度解析:塑造未来企业的关键策略

在当今技术飞速发展的背景下&#xff0c;数字化转型&#xff08;_Digital Transformation_&#xff09;已成为企业保持竞争力的必要手段。随着云计算、物联网&#xff08;IoT&#xff09;、大数据和人工智能等技术的不断成熟&#xff0c;企业通过数字化手段优化业务流程、提升客…

ESXI 的下载 2024 版

ESXI 的下载 前言 最近收到了部分小伙伴的反馈&#xff0c;VMware 的下载官网上 ESXI 自动跳转进入了 BroadCom 的支持页面&#xff0c;难以找到 ESXI 的官方资源&#xff0c;这里我将为大家做出下载的相关指引。 ESXI 下载指引 跳转进入 BroadCom 的支持页面 &#x1f449; …

Python | Leetcode Python题解之第467题环绕字符串中唯一的子字符串

题目&#xff1a; 题解&#xff1a; class Solution:def findSubstringInWraproundString(self, p: str) -> int:dp defaultdict(int)k 0for i, ch in enumerate(p):if i > 0 and (ord(ch) - ord(p[i - 1])) % 26 1: # 字符之差为 1 或 -25k 1else:k 1dp[ch] max…

Web Service Sender ParseError Invalid byte 1 of 1-byte UTF-8 sequence

说明 发送webservice报错 Invalid UTF-8 start byte 0xfc when using Web Service Sender Web Service Sender error ERROR MESSAGE: Error creating web service dispatch com.sun.xml.ws.streaming.XMLStreamReaderException: XML reader error: javax.xml.stream.XMLStream…

k8s之ingress-nginx-controller安装

作者&#xff1a;程序那点事儿 日期&#xff1a;2024/01/30 01:25 要在master节点上安装 helm repo add ingress-nginx Welcome - Ingress-Nginx Controller helm search repo ingress-nginx helm pull ingress-nginx/ingress-nginx --version 4.4.2 mv ingress-nginx-4.4.…

为Floorp浏览器添加搜索引擎及搜索栏相关设置. 2024-10-08

Floorp浏览器开源项目地址: https://github.com/floorp-Projects/floorp/ 以下内容同样适用于firefox和大部分基于firefox的桌面版浏览器 1.第一步 为Floorp浏览器添加搜索栏 (1.工具栏空白处 次键选择 定制工具栏 (2. 把 搜索框 拖动至工具栏 2.添加搜索引擎 以添加 搜狗搜索…

Ubuntu 18.04安装storcli查看阵列信息

rootCeph03:/opt/MegaRAID/storcli# cat /etc/issue Ubuntu 18.04.5 LTS \n \l 准备好storcli的安装包 解压 解压之后可以看到 根据系统版本选择 把storcli_1.18.11_all.deb包传到服务器 使用命令dpkg -I storcli_1.18.11_all.deb ./storcli64 show ./storcli64 /c1 show …

Acwing 贪心算法遗留

1.Huffman树 Acwing 148.合并果子 实现思路&#xff1a;构建一颗哈夫曼树&#xff0c;求最短带权路径长度&#xff08;树中所有的叶结点的权值乘上其到根结点的路径长度&#xff09; 每次选择重量最小的两堆进行合并使用小根堆存储每一堆果子&#xff0c;每次两次弹出堆顶元…

ML 系列:机器学习和深度学习的深层次总结( 15) — KNN — 第 1 部分

一、说明 K-最近邻 (KNN) 算法是一种流行的监督机器学习算法&#xff0c;用于分类和回归任务。它是非参数惰性学习算法的一个典型例子。KNN 被认为是一种惰性学习算法&#xff0c;因为它在训练阶段不对底层数据分布做出任何假设&#xff0c;也不从训练数据中学习特定模型。相反…