当前位置:首页 > 技术 > 正文内容

Django ORM 核心操作详解

访客 技术 2026年7月8日 1

基础查询方法

掌握以下核心查询方法是使用 Django ORM 的基础:

<1> all():                  获取全部记录
 
<2> filter(**kwargs):       筛选符合条件的对象集合
 
<3> get(**kwargs):          获取唯一匹配对象,多重或无匹配会报错
 
<4> exclude(**kwargs):      排除符合条件的对象
 
<5> values(*field):         返回字典形式的查询结果
 
<6> values_list(*field):    返回元组形式的查询结果
 
<7> order_by(*field):       按指定字段排序结果
 
<8> reverse():              反转查询结果顺序
 
<9> distinct():             去除重复记录
 
<10> count():               统计匹配对象数量
 
<11> first():               获取首条记录
 
<12> last():                获取末条记录
 
<13> exists():              判断是否存在匹配记录

返回 QuerySet 的方法

  • all()
  • filter()
  • exclude()
  • order_by()
  • reverse()
  • distinct()

特殊 QuerySet 类型

  • values() - 返回字典序列
  • values_list() - 返回元组序列

返回具体对象的方法

  • get()
  • first()
  • last()

返回布尔值的方法

  • exists()

返回数值的方法

  • count()

双下划线查询技巧

models.Product.objects.filter(id__lt=10, id__gt=1)     # id 在 1-10 之间
models.Product.objects.filter(id__in=[11, 22, 33])     # id 匹配列表值
models.Product.objects.exclude(id__in=[11, 22, 33])    # id 不在列表中
models.Product.objects.filter(name__contains="tech")   # 名称包含特定字符
models.Product.objects.filter(name__icontains="tech")  # 忽略大小写包含
models.Product.objects.filter(id__range=[1, 3])        # 范围查询
models.Product.objects.filter(create_time__year=2023)  # 按年份筛选日期

外键关系操作

正向查询

对象方式:

product_obj = models.Product.objects.first()
print(product_obj.category)           # 关联分类对象
print(product_obj.category.name)      # 分类名称

字段方式:

models.Product.objects.values_list("category__name")

反向查询

对象方式:

category_obj = models.Category.objects.first()
products = category_obj.product_set.all()        # 该分类下的所有产品
titles = products.values_list("title")           # 产品标题列表

字段方式:

models.Category.objects.values_list("product__title")

多对多关系管理

RelatedManager 方法

create() - 创建并关联新对象

models.Author.objects.first().book_set.create(
    title="Python进阶", 
    publish_date=datetime.date.today()
)

add() - 添加现有对象到关联集合

author_list = models.Author.objects.filter(id__lt=3)
models.Book.objects.first().authors.add(*author_list)

# 或使用 ID
models.Book.objects.first().authors.add(*[1, 2])

set() - 更新整个关联集合

book_obj = models.Book.objects.first()
book_obj.authors.set([2, 3])

remove() - 移除指定关联对象

book_obj = models.Book.objects.first()
book_obj.authors.remove(3)

clear() - 清空所有关联

book_obj = models.Book.objects.first()
book_obj.authors.clear()

聚合与分组查询

聚合查询

from django.db.models import Avg, Sum, Max, Min, Count

# 基础聚合
models.Book.objects.all().aggregate(Avg("price"))
# {'price__avg': 13.233333}

# 自定义聚合名
models.Book.objects.aggregate(avg_price=Avg('price'))
# {'avg_price': 13.233333}

# 多重聚合
models.Book.objects.all().aggregate(
    Avg("price"), 
    Max("price"), 
    Min("price")
)

分组查询

# 按出版社分组统计最低价格
models.Publisher.objects.annotate(
    min_price=Min("book__price")
).values("name", "min_price")

# 统计每本书作者数量
models.Book.objects.all().annotate(
    author_count=Count("author")
)

# 查询多作者书籍
models.Book.objects.annotate(
    author_count=Count("author")
).filter(author_count__gt=1)

F 表达式与 Q 对象

F 表达式

用于字段间比较和更新:

from django.db.models import F

# 查询评论数大于收藏数的书籍
models.Book.objects.filter(comment_num__gt=F('favorite_num'))

# 数值运算
models.Book.objects.filter(comment_num__lt=F('favorite_num')*2)

# 字段更新
models.Book.objects.all().update(price=F("price")+30)

# 字符串字段更新
from django.db.models.functions import Concat
from django.db.models import Value

models.Book.objects.all().update(
    title=Concat(F("title"), Value("(第2版)"))
)

Q 对象

实现复杂逻辑查询:

# OR 查询
models.Book.objects.filter(
    Q(authors__name="张三") | Q(authors__name="李四")
)

# AND + NOT 组合
models.Book.objects.filter(
    Q(author__name="王五") & ~Q(publish_date__year=2023)
)

# 参数混合使用(Q对象需在前)
models.Book.objects.filter(
    Q(publish_date__year=2023) | Q(publish_date__year=2022),
    title__icontains="教程"
)

并发控制与事务

行级锁

# SELECT ... FOR UPDATE
entries = Entry.objects.select_for_update().filter(
    author=request.user
)

# 非阻塞锁
Entry.objects.select_for_update(nowait=True)

# 跳过已锁定行
Entry.objects.select_for_update(skip_locked=True)

事务处理

try:
    from django.db import transaction
    with transaction.atomic():
        publisher = models.Publisher.objects.create(
            name="新星出版社"
        )
        models.Book.objects.create(
            title="Django实战",
            publisher=publisher
        )
except Exception as e:
    print(f"事务失败: {e}")

原生 SQL 执行

使用 raw() 方法

# 基础原生查询
for person in Person.objects.raw('SELECT * FROM myapp_person'):
    print(person)

# 字段映射
Person.objects.raw(
    'SELECT id, first_name as fname FROM myapp_person',
    translations={'first_name': 'fname'}
)

# 带参数查询
Person.objects.raw(
    'SELECT * FROM myapp_person WHERE id > %s',
    params=[1]
)

直接执行 SQL

from django.db import connection

cursor = connection.cursor()
cursor.execute("SELECT * FROM auth_user WHERE id = %s", [1])
result = cursor.fetchone()

调试工具

在 settings.py 中启用 SQL 日志:

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

独立脚本中使用 Django ORM

import os

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "project.settings")
import django
django.setup()

from app.models import Book
books = Book.objects.all()
print(books)

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

linux screen 用法详情 (nohup 的替代方案)

一、screen 是什么?能干嘛?screen 是一个终端复用器,可以:在一个 SSH 会话中开多个“虚拟终端”SSH 断线后,程序仍然在后台运行随时重新连接到原来的会话特别适合:nohup 的替代方案跑脚本 / 爬虫 / 训练模型运维、远程开发二、安装 screen# CentOS / Rocky / Almayum install -y screen# Debian / Ubuntuapt i...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。