Django基础教程(十八)初识 Django QuerySet:Django的隐形超能力:初识QuerySet,你的数据库“魔法棒”!

深度分析Django基础教程之初识QuerySet

朋友们,兄弟们,代码摸鱼者们!今天咱们不聊Django怎么安装,也不扯什么MTV模式。那些都是基本功,是扎马步。今天,我要带你解锁Django世界里一个真正让你“起飞”的技能——QuerySet

你可以把它想象成Django送给你的一个万能遥控器。你想对数据库里的数据做点啥,比如“把所有名字里带‘帅’的用户找出来”、“把点赞数超过100的文章按时间倒序排好”、“把商品库存自动减一”……你不用苦哈哈地去写那些又臭又长的SQL语句,只需要用Python的风格,像搭乐高一样,轻松写几行代码,QuerySet就会在背后帮你把一切搞定。

更神奇的是,这根“魔法棒”还自带**“懒癌”属性“链式”绝技**,用好了你就能大喊一声:“键来!”(不对,是“数据来!”)。

一、QuerySet到底是啥?它不是列表,是“承诺”!

刚入门的小伙伴最容易产生的误解就是:Article.objects.all() 这不就是返回了一个包含所有文章的列表吗?

错!大错特错!

你看到的 Article.objects.all(),它返回的不是数据本身,而是一个 “数据的承诺”,或者说是一张 “还没兑奖的彩票”

# 想象你在奶茶店点单
queryset = Article.objects.all() # 你只是对店员说:“把你们店里所有奶茶都给我准备好。”

# 这时候,店员(Django)只是记下了你的要求,但根本没开始动手做奶茶。
# 所以,数据库此时还没有任何查询操作!这,就是“懒惰”的奥秘。

# 什么时候店员才开始真正做奶茶呢?
for article in queryset: # 当你说:“好了,现在一杯一杯拿给我。”
    print(article.title)

# 或者
list(queryset) # 当你说:“别一杯一杯了,全部打包到一个袋子里给我。”

# 甚至
if queryset: # 当你需要检查“你到底有没有奶茶”时。
    print("Yes, we have articles!")

这个“懒惰”的特性,是QuerySet最核心的魔法。它意味着你可以不断地、链式地修饰你的查询,而Django会积攒你的所有指令,直到非用不可的那一刻,才会一次性访问数据库,生成最有效的SQL语句。

这避免了大量不必要的数据库查询,性能蹭蹭往上涨!

二、QuerySet核心“咒语”大全:从入门到上头

好了,我们知道QuerySet很“懒”了。那怎么驱使这个“懒家伙”为我们干活呢?当然是靠各种强大又优雅的“咒语”(方法)啦!

1. 基础筛选三剑客:all, filter, get, exclude

  • all(): “我全都要!”——获取某个模型下的所有对象。
  • filter(**kwargs): “我要符合条件的!”——这是你最常用的,相当于SQL的WHERE
# 找出所有标题中包含“Django”的文章
django_articles = Article.objects.filter(title__contains='Django')

# 找出所有发布时间在2023年之后且点赞数大于50的文章
popular_recent_articles = Article.objects.filter(
    publish_date__year__gte=2023,
    likes__gt=50
)
# 看,像不像在说人话?
  • get(**kwargs): “我只要那一个,独一无二的!”——返回唯一匹配的对象。如果没找到会抛DoesNotExist异常,找到多个会抛MultipleObjectsReturned异常。用于你确信存在且唯一的情况,比如根据主键查。
# 根据主键ID获取一篇文章
try:
    that_article = Article.objects.get(id=1)
except Article.DoesNotExist:
    print("文章不存在哦!")
  • exclude(**kwargs): “除了这些,我都要!”——排除符合条件的数据。
# 找出所有不是草稿状态的文章
published_articles = Article.objects.exclude(status='draft')

2. “链式施法”:把复杂查询写成一首诗

这是QuerySet最优雅的地方!它的多数方法都会返回一个新的QuerySet,所以你可以像链条一样一个接一个地调用。

# 一个复杂的查询:找出2023年发布的,标题不含“测试”,并且点赞数大于10的文章,按发布时间倒序排列。
result = Article.objects.all() \
                       .filter(publish_date__year=2023) \
                       .exclude(title__contains='测试') \
                       .filter(likes__gt=10) \
                       .order_by('-publish_date')

# 看,这一长串逻辑,读起来是不是非常顺畅?
# Django最终会把这一串链式调用,组合成一条高效的SQL语句执行。

3. 进阶魔法:F对象Q对象

当你觉得上面的操作只是小打小闹时,真正的魔法来了。

  • F对象:自己跟自己比!
    通常,你只能拿模型的字段和一个常量比较。但如果你想拿一个字段和另一个字段比较呢?
from django.db.models import F

# 找出所有“评论数”大于“点赞数”的文章(这是什么奇葩文章?)
weird_articles = Article.objects.filter(comment_count__gt=F('likes'))

# 更实用的:将所有文章的点赞数+1
Article.objects.update(likes=F('likes') + 1)
# 一条SQL搞定,不需要先取出数据,再用Python计算,最后保存。避免了并发问题!
  • Q对象:构建复杂的逻辑关系(与或非)
    filter里的多个条件是AND关系。如果你想用OR或者NOT怎么办?Q对象闪亮登场!
from django.db.models import Q

# 找出标题包含“Django” OR 标题包含“Python”的文章
articles = Article.objects.filter(
    Q(title__contains='Django') | Q(title__contains='Python')
)

# 找出作者是“小明” AND (状态是“已发布” OR 点赞数>100)的文章
complex_articles = Article.objects.filter(
    Q(author='小明') & (Q(status='published') | Q(likes__gt=100))
)
# 这不就是SQL里的括号吗?用Q对象,再复杂的逻辑也能清晰表达。
三、完整示例:打造一个迷你博客文章管理器

光说不练假把式,让我们来亲手搭建一个场景,看看QuerySet在实战中多么威武。

1. 模型定义 (models.py)

from django.db import models

class Article(models.Model):
    STATUS_CHOICES = (
        ('draft', '草稿'),
        ('published', '已发布'),
        ('archived', '归档'),
    )

    title = models.CharField(max_length=200, verbose_name='标题')
    content = models.TextField(verbose_name='内容')
    author = models.CharField(max_length=100, default='匿名侠', verbose_name='作者')
    publish_date = models.DateTimeField(auto_now_add=True, verbose_name='发布时间') # 创建时自动设置
    status = models.CharField(max_length=10, choices=STATUS_CHOICES, default='draft', verbose_name='状态')
    likes = models.PositiveIntegerField(default=0, verbose_name='点赞数')
    comment_count = models.PositiveIntegerField(default=0, verbose_name='评论数')

    def __str__(self):
        return self.title

    class Meta:
        db_table = 'article' # 自定义表名
        ordering = ['-publish_date'] # 默认按发布时间倒序排列

(记得 python manage.py makemigrationspython manage.py migrate 哦!)

2. 在Django Shell中施展魔法

打开 python manage.py shell,我们来玩转数据。

# 导入模型
from myapp.models import Article
from django.db.models import F, Q
from datetime import datetime

# 1. 创建一些测试数据(这里简单创建,实际项目会用Fixtures或管理后台)
Article.objects.create(title="我的第一篇Django文章", content="...", status='published', likes=10)
Article.objects.create(title="Python入门指南", content="...", status='published', likes=25, comment_count=30)
Article.objects.create(title="一个未完成的草稿", content="...", status='draft')
Article.objects.create(title="Django QuerySet深度研究", content="...", status='published', likes=50, comment_count=45)
Article.objects.create(title="归档的老新闻", content="...", status='archived', likes=5)

# 2. 基础查询:获取所有已发布文章
published = Article.objects.filter(status='published')
for article in published:
    print(f"- {article.title} (点赞: {article.likes})")

# 3. 链式查询:获取最近发布的、点赞超过20的已发布文章,并按点赞数排序
popular = Article.objects.filter(status='published').filter(likes__gte=20).order_by('-likes')
print("\n--- 热门文章 ---")
for article in popular:
    print(f"- {article.title} (点赞: {article.likes})")

# 4. 使用Q对象:搜索标题含有“Django”或“Python”的已发布文章
search_results = Article.objects.filter(
    status='published'
).filter(
    Q(title__contains='Django') | Q(title__contains='Python')
)
print("\n--- 搜索结果 ---")
for article in search_results:
    print(f"- {article.title}")

# 5. 使用F对象:找出评论比点赞还多的“争议”文章
controversial = Article.objects.filter(comment_count__gt=F('likes'))
print("\n--- 争议文章(评论>点赞)---")
for article in controversial:
    print(f"- {article.title} (赞: {article.likes}, 评: {article.comment_count})")

# 6. 性能相关:使用`only`只获取需要的字段,避免查询所有数据(适用于大文本字段)
# 假设content字段很大,我们只需要标题和作者
lightweight_articles = Article.objects.filter(status='published').only('title', 'author')
for article in lightweight_articles:
    print(f"- {article.title} by {article.author}") # 此时访问content才会触发额外查询
四、总结:让你的Django技能“起飞”

看到这里,你是不是对QuerySet刮目相看了?它绝不仅仅是一个简单的数据获取工具,而是一个功能丰富、设计精巧的查询构建器

记住它的三大特性:

  1. 懒惰(Lazy):不评估不查询,性能优化的基石。
  2. 链式(Chainable):让复杂查询的构建过程清晰、易读、易维护。
  3. 强大(Powerful)F对象Q对象让你拥有应对任何复杂业务场景的能力。

下次当你写Django代码时,请有意识地多用用QuerySet的这些高级特性。别再手动循环过滤,别再写重复的代码。用好这根“魔法棒”,你会发现,和数据库打交道,原来可以如此轻松、优雅和高效。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

值引力

持续创作,多谢支持!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值