Python web实战之 Django 的 ORM 框架详解

8d8e8b4196f2412ba8d5e7e961cf7823.png


本文关键词:Python、Django、ORM。

概要

在 Python Web 开发中,ORM(Object-Relational Mapping,对象关系映射)是一个非常重要的概念。ORM 框架可以让我们不用编写 SQL 语句,就能够使用对象的方式来操作数据库,大大提高了代码的可读性和可维护性。Django 作为一款流行的 Web 框架,自带了强大的 ORM 框架。

本文将会详细介绍 Django 的 ORM 框架,包括基本使用方法、高级查询、性能优化等方面。


 

1. 基本使用方法

1.1 定义模型类

在 Django 里可以使用模型类来定义数据库表。模型类需要继承自 django.db.models.Model,并且定义表的各个字段。例如,下面是一个简单的模型类,用来表示一个博客文章:

from django.db import models

class Blog(models.Model):
    title = models.CharField(max_length=100)
    content = models.TextField()
    pub_date = models.DateTimeField(auto_now_add=True)

上面的代码定义了一个 Blog 类来表示博客文章。这个类继承自 django.db.models.Model,并且定义了三个字段:标题、内容和发布日期。其中,标题和内容都是字符串类型,使用 CharField 和 TextField 来定义。pub_date 是一个日期时间类型,使用 DateTimeField 来定义。auto_now_add=True 表示在创建新记录时自动设置为当前时间。

1.2 创建表

定义完模型类之后,我们需要创建对应的数据库表。在 Django 中,可以使用 manage.py 命令来进行数据库迁移操作。具体来说,我们需要执行以下两个命令:

# 生成迁移文件
python manage.py makemigrations

# 执行迁移操作
python manage.py migrate

执行完上面的两个命令之后,Django 会根据模型类自动生成对应的数据库表。

注意:在进行迁移操作之前,请确保已经仔细确认了所有相关设置和代码,并且备份了数据。

1.3 插入数据

插入数据可以使用模型类来表示一条记录,并且调用 save() 方法来将记录保存到数据库中。例如,下面的代码演示了如何向 Blog 表中插入一条记录:

blog = Blog(title='Hello World', content='This is my first blog post.')
blog.save()

1.4 查询数据

查询数据可以使用模型类的 objects 属性,该属性是 Manager 类的实例,提供了各种查询方法。例如从 Blog 表中查询所有记录:

blogs = Blog.objects.all()

for blog in blogs:
    print(blog.title, blog.content, blog.pub_date)

1.5 更新数据

更新数据可以先查询出需要更新的记录,然后修改对应的字段,最后调用 save() 方法进行保存。例如将 Blog 表中所有记录的标题修改为 'Hello Django'

blogs = Blog.objects.all()

for blog in blogs:
    blog.title = 'Hello Django'
    blog.save()

1.6 删除数据

删除数据可以先查询出需要删除的记录,然后调用 delete() 方法进行删除。例如删除 Blog 表中所有记录:

blogs = Blog.objects.all()

for blog in blogs:
    blog.delete()

 

2. 高级查询

2.1 条件查询

Django 的 ORM 框架提供了非常方便的条件查询功能。例如查询 Blog 表中标题为 'Hello World' 的记录:

blogs = Blog.objects.filter(title='Hello World')

for blog in blogs:
    print(blog.title, blog.content,blog.pub_date)

可以看到,我们使用了 filter() 方法来指定查询条件,其中 title='Hello World' 表示标题等于 'Hello World'filter() 方法返回一个 QuerySet 对象,可以使用 for 循环遍历查询结果。

2.2 聚合查询

聚合查询可以使用 aggregate() 方法来实现。例如统计 Blog 表中记录的数量:

from django.db.models import Count

count = Blog.objects.aggregate(Count('id'))
print(count['id__count'])

可以看到,我们使用了 aggregate() 方法来指定聚合操作,其中 Count('id') 表示统计 id 字段的数量。aggregate() 方法返回一个字典,其中键是聚合操作的名称(例如,id__count 表示统计数量),值是聚合操作的结果。

2.3 连接查询

连接查询可以使用 select_related() 方法和 prefetch_related() 方法来实现。例如,下面的代码演示了如何查询 Blog 表中的记录,并且同时连接查询关联的 Author 表中的作者信息:

class Author(models.Model):
    name = models.CharField(max_length=50)

class Blog(models.Model):
    title = models.CharField(max_length=100)
    content = models.TextField()
    pub_date = models.DateTimeField(auto_now_add=True)
    author = models.ForeignKey(Author, on_delete=models.CASCADE)

blogs = Blog.objects.select_related('author')

for blog in blogs:
    print(blog.title, blog.content, blog.pub_date, blog.author.name)

可以看到,我们使用了 select_related('author') 方法来指定需要连接查询的外键字段(即 author 字段),这样就可以同时查询 Blog 表和 Author 表中的数据。注意,select_related() 方法只能用于一对一和多对一关系的查询,上面的例子是多对一关系。

2.4 原生 SQL 查询

Django 的 ORM 框架也支持原生 SQL 查询。例如使用原生 SQL 查询 Blog 表中的记录:

from django.db import connection

with connection.cursor() as cursor:
    cursor.execute("SELECT * FROM myapp_blog")
    blogs = cursor.fetchall()

for blog in blogs:
    print(blog[1], blog[2], blog[3])

可以看到,我们使用了 connection.cursor() 方法来获取数据库连接的游标,然后调用 execute() 方法执行 SQL 查询。最后,使用 fetchall() 方法获取查询结果。

 

3. 性能优化

3.1 使用索引

索引是提高数据库查询性能的重要手段。在 Django 中,可以使用 db_index=True 参数来为字段创建索引。例如为 title 字段创建索引:

class Blog(models.Model):
    title = models.CharField(max_length=100, db_index=True)
    content = models.TextField()
    pub_date = models.DateTimeField(auto_now_add=True)

3.2 批量操作

批量操作可以使用 bulk_create() 方法和 bulk_update() 方法来实现。例如,下面的代码演示了如何批量插入 Blog 表中的记录:

blogs = [
    Blog(title='Blog 1', content='Content 1'),
    Blog(title='Blog 2', content='Content 2'),
    Blog(title='Blog 3', content='Content 3'),
]

Blog.objects.bulk_create(blogs)

可以看到,我们使用了 bulk_create() 方法来批量插入记录,其中 blogs 是一个包含多个 Blog 实例的列表。

3.3 延迟加载

延迟加载可以使用 defer() 方法和 only() 方法来实现。

使用 defer() 方法时,Django 将不会立即从数据库中获取指定字段的数据。它会在需要访问这些字段的数据时,再去查询数据库。这样可以避免一次性从数据库中取出大量的数据,减轻数据库的负担,提高查询效率。

使用 only() 方法可以指定只查询需要的字段,而不是查询整个表的所有字段。这样可以减少数据传输的大小,节省网络带宽和内存资源,提高查询效率。

例如延迟加载 Blog 表中的记录,并且只查询 title 和 pub_date 两个字段:

blogs = Blog.objects.defer('content').only('title', 'pub_date')

for blog in blogs:
    print(blog.title, blog.pub_date)

可以看到,我们使用了 defer('content') 方法来延迟加载 content 字段,这样查询结果中就不会包含 content 字段的数据。同时,使用 only('title', 'pub_date') 方法来指定只查询 title 和 pub_date 两个字段的数据。

3.4 缓存查询结果

缓存查询结果可以使用 Django 的缓存框架来实现。Django的缓存框架可以配置为使用不同的缓存后端,下面是常见的几种缓存后端的配置方法:

3.4.1 内存缓存

使用内存缓存作为缓存后端是最简单的配置方式,它可以快速地缓存数据并且不需要额外的配置。在settings.py文件中进行如下配置:

CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
        'LOCATION': 'unique-snowflake',
    }
}

BACKEND 指定了缓存后端为内存缓存,LOCATION 是一个可选的参数,用于指定缓存的名称,可以是任何字符串。

3.4.2 文件缓存

使用文件缓存作为缓存后端可以将缓存数据存储到文件系统中,需要指定缓存文件的路径。在settings.py文件中进行如下配置:

CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
        'LOCATION': '/var/tmp/django_cache',
    }
}

BACKEND 指定了缓存后端为文件缓存,LOCATION 是一个必选的参数,用于指定缓存文件的路径。

3.4.3 Memcached

使用Memcached作为缓存后端可以将缓存数据存储到Memcached服务器中,需要指定Memcached服务器的地址和端口号。在settings.py文件中进行如下配置:

CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
        'LOCATION': '127.0.0.1:11211',
    }
}

BACKEND 指定了缓存后端为Memcached,LOCATION 是一个必选的参数,用于指定Memcached服务器的地址和端口号。

3.4.4 Redis

使用Redis作为缓存后端可以将缓存数据存储到Redis服务器中,需要指定Redis服务器的地址、端口号和数据库编号。在settings.py文件中进行如下配置:

CACHES = {
    'default': {
        'BACKEND': 'django_redis.cache.RedisCache',
        'LOCATION': 'redis://127.0.0.1:6379/0',
        'OPTIONS': {
            'CLIENT_CLASS': 'django_redis.client.DefaultClient',
        },
    }
}

BACKEND 指定了缓存后端为Redis,LOCATION 是一个必选的参数,用于指定Redis服务器的地址、端口号和数据库编号。OPTIONS 是一个可选的参数,用于指定Redis客户端的选项,这里使用默认选项。

需要注意的是,在使用Redis作为缓存后端时,需要额外安装 django-redis 库。可以使用pip命令进行安装:

pip install django-redis

例如缓存 Blog 表中的记录:

from django.core.cache import cache

blogs = cache.get('blogs')

if blogs is None:
    blogs = Blog.objects.all()
    cache.set('blogs', blogs, timeout=3600)

for blog in blogs:
    print(blog.title, blog.content, blog.pub_date)

可以看到,我们使用了 cache.get('blogs') 方法来从缓存中获取查询结果。如果缓存中不存在查询结果,则使用 Blog.objects.all() 来查询数据库,并且使用 cache.set('blogs', blogs, timeout=3600) 方法将查询结果存入缓存中。其中,timeout=3600 表示缓存的过期时间为 3600 秒。

 

技术总结

本文详细介绍了 Django 的 ORM 框架,包括基本使用方法、高级查询和性能优化等方面。ORM 框架可以让我们不用编写 SQL 语句,就能够使用对象的方式来操作数据库,大大提高了代码的可读性和可维护性。同时,我们还介绍了一些性能优化技巧,例如使用索引、批量操作、延迟加载和缓存查询结果等。希望本文对你学习 Django 的 ORM 框架有所帮助!

 

欢迎点赞收藏转发,感谢🙏

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

vue3+uniapp自定义tabbar

首先把tabbar中的元素写在一个list中用v-for进行渲染 用一个interface进行定义接口,这样别人在review你的代码就可以清晰知道你的tabbar包含什么元素。 利用typescript特性进行类型定义,可以省去很多麻烦 import { reactive } from "vue" imp…

Android kotlin系列讲解之最佳的UI体验 - Material Design 实战

目录 一、什么是Material Design二、Toolbar三、滑动菜单1、DrawerLayout2、NavigationView 四、悬浮按钮和可交互提示1、FloatingActionButton2、Snackbar3、CoordinatorLayout 五、卡片式布局1、MaterialCardView2、AppBarLayout 六、可折叠式标题栏1、CollapsingToolbarLayo…

无脑入门pytorch系列(一)—— nn.embedding

本系列教程适用于没有任何pytorch的同学(简单的python语法还是要的),从代码的表层出发挖掘代码的深层含义,理解具体的意思和内涵。pytorch的很多函数看着非常简单,但是其中包含了很多内容,不了解其中的意思…

线扫激光算法原理

一:线扫激光算法原理 激光器发出的激光束经准直聚焦后垂直入射到物体表面上,表面的散射光由接收透镜成像于探测器的阵列上。光敏面于接收透镜的光轴垂直。如图: 当被测物体表面移动x,反应到光敏面上像点位移为x’。a为接收透镜到物体的距离(物距),b为接收后主面到成像…

SQL-每日一题【1174. 即时食物配送 II】

题目 配送表: Delivery 如果顾客期望的配送日期和下单日期相同,则该订单称为 「即时订单」,否则称为「计划订单」。 「首次订单」是顾客最早创建的订单。我们保证一个顾客只会有一个「首次订单」。 写一条 SQL 查询语句获取即时订单在所有用户的首次订…

无人驾驶实战-第一课(自动驾驶概述)

在七月算法上报了《无人驾驶实战》课程,老师讲的真好。好记性不如烂笔头,记录一下学习内容。 课程入口,感兴趣的也可以跟着学一下。 ————————————————————————————————————————— 无人驾驶汽车的定义…

HTTP——五、与HTTP协作的Web服务器

HTTP 一、用单台虚拟主机实现多个域名二、通信数据转发程序 :代理、网关、隧道1、代理2、网关3、隧道 三、保存资源的缓存1、缓存的有效期限2、客户端的缓存 一台 Web 服务器可搭建多个独立域名的 Web 网站,也可作为通信路径上的中转服务器提升传输效率。…

windows服务器iis PHP套件出现FastCGI等错误解决方法汇总

如果您的服务器安装了PHP套件,出现了无法打开的情况,请参照如下办法解决: 首先,需要设置IIS允许输出详细的错误信息到浏览器,才好具体分析 错误一: 处理程序“FastCGI”在其模块列表中有一个错误模块“Fast…

应用案例|基于3D视觉的高反光金属管件识别系统解决方案

Part.1 项目背景 在现代制造业中,高反光金属管件的生产以及质量的把控是一个重要的挑战。传统的2D视觉系统常常难以准确地检测和识别高反光金属管件,因为它们的表面特征不够明显,容易受到光照和阴影的干扰。为了应对这个问题,基于…

UE5 c++ 的文件操作(记录备忘)

函数库.h // Fill out your copyright notice in the Description page of Project Settings.#pragma once#include "CoreMinimal.h" #include "Kismet/BlueprintFunctionLibrary.h" #include "Microsoft/AllowMicrosoftPlatformTypes.h" #incl…

windows编译ncnn

官方代码https://github.com/Tencent/ncnn/wiki/how-to-build#build-for-windows-x64-using-visual-studio-community-2017 编译工具 visual studio 2017 一、编译protobuf 1、下载protobuf protobuf-3.11.2:https://github.com/google/protobuf/archive/v3.11…

基于SpringBoot+Vue的在线考试系统设计与实现(源码+LW+部署文档等)

博主介绍: 大家好,我是一名在Java圈混迹十余年的程序员,精通Java编程语言,同时也熟练掌握微信小程序、Python和Android等技术,能够为大家提供全方位的技术支持和交流。 我擅长在JavaWeb、SSH、SSM、SpringBoot等框架…

HarmonyOS学习路之方舟开发框架—学习ArkTS语言(状态管理 三)

Link装饰器:父子双向同步 子组件中被Link装饰的变量与其父组件中对应的数据源建立双向数据绑定。 概述 Link装饰的变量与其父组件中的数据源共享相同的值。 装饰器使用规则说明 Link变量装饰器 说明 装饰器参数 无 同步类型 双向同步。 父组件中State, Stor…

Linux常用命令——dpkg-deb命令

在线Linux命令查询工具 dpkg-deb Debian Linux下的软件包管理工具 补充说明 dpkg-deb命令是Debian Linux下的软件包管理工具,它可以对软件包执行打包和解包操作以及提供软件包信息。 语法 dpkg-deb(选项)(参数)选项 -c:显示软件包中的文件列表&am…

springBoot项目导入外部jar包

一、将外部的jar包复制到指定文件夹 二、修改pom文件 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocati…

专家论道: 唐贤香云纱塑造中国非遗国际品牌

自“香云纱染整技艺”入选第二批国家级非物质文化遗产以来&#xff0c;被誉为纺织界“软黄金”的香云纱&#xff0c;重新焕发青春&#xff0c;频频登上时尚舞台&#xff0c;以不一样的面貌展示在世人面前&#xff0c;成为服装设计师、消费者青睐的材质。而随着北京卫视播出的《…

Win10查询硬盘序列号

添加wmic命令 winR cmd命令 wmic diskdrive get model, serialnumber

java -jar指定外部配置文件

场景 spingboot项目部署jar时,需要时常修改配置,为了方便,将配置文件放到jar包外 操作步骤 在jar包同级目录下创建config文件夹(位置没有强制要求,为了方便而已) 在jar包同级目录下创建start.bat文件,并编辑内容 echo off :: 命令窗口标题 title yudibei_performance_tes…

Spring-1-透彻理解Spring XML的必备知识

学习目标 能够说出Spring的体系结构 能够编写IOC-DI快速入门 思考:为什么学习Spring而不是直接学习SpringBoot 1 Spring介绍 思考:我们为什么要学习Spring框架&#xff1f; 工作上面 Java拥有世界上数量最多的程序员 最多的岗位需求与高额薪资 95%以上服务器端还是要用Jav…

【Apifox】Apifox设置全局Token:

文章目录 一、获取登录Token和设置全局变量&#xff1a;二、设置全局参数&#xff1a;三、效果&#xff1a; 一、获取登录Token和设置全局变量&#xff1a; 二、设置全局参数&#xff1a; 三、效果&#xff1a;