美文网首页
1.5 使用查询集(QuerySets) 和 管理器(manag

1.5 使用查询集(QuerySets) 和 管理器(manag

作者: gznb | 来源:发表于2020-07-20 16:18 被阅读0次

    1. 使用查询集(QuerySets) 和 管理器(managers)

    现在你有一个功能比较完备的管理员站点来管理你的博客内容,接下来的时间将去学习如何从数据库中检索信息并且和它交互。Django 附带了一个功能强大并且简单的的数据库抽象 API 去让你 创建、检索、更新、删除对象。Django 的对象关系模型 (ORM) 兼容 MySQL, PostgreSQL, SQLite, Oracle, MariaDB。你可以在项目的 settings.py 文件中 DATABASES 参数定义你要使用的数据库。Django 可以在同一时间使用多个数据库,并且你可以对数据库路由进行编程去自定义一个路由模式。

    一旦你创建了一个数据模型,Django 就提供一个免费的API来与它们交互。你可以在这个官方文档中找到有关数据模型的参考。

    Django 的 ORM 是基于 查询集(QuerySets) 的。查询集是从数据库检索对象的数据库查询的集合。你可以在查询集上应用过滤器,以根据给定的参数缩小查询的结果。

    2. 创建对象

    在终端中运行下面的命令打开一个 Python shell:

    python manage.py shell

    输入下面的命令:

    Snipaste_2020-07-17_15-14-23.jpg

    让我们来分析以下这些代码,首先,检索用户名为 adminuser对象:

    user = User.objects.get(username='admin')

    get() 方法允许你从数据库中检索出单个对象,注意,该方法期望得到与查询匹配的结果。如果数据库没有返回任何结果,这个方法将会抛出一个 DoesNotExist 异常,如果数据库返回了多个结果,它将抛出一个 MultipleObjectsReturned 异常。这两个异常都是执行查询的模型类的属性。

    现在通过自定义 title, slug, body,并将之间检索到的用户设置为该 文章的作者。

    post = Post(title=' Another post' , slug=' another-post' , body=' Post body. ' , author=user)

    此对象在内存中,没有持久化到数据库中。

    最后,你通过使用 save() 方法把 Post 对象保存到数据库中:

    post.save()

    前面的操作在后台执行 INSERT SQL 语句,你已经了解了如何 首先在内存中创建对象,然后将其持久化到数据库中,但是也可以使用 create() 方法在单个操作中创建对象并将其持久化到数据库中,如下所示:

    Post.objects.create(title=' Another post' , slug=' another-post' , body=' Post body. ' , author=user)

    3. 更新对象

    现在,将文章标题更改为不同的内容并再次保存对象:

    post.title = 'new title'
    post.save()
    

    这是,这个save() 方法将执行一个 UPDATE SQL 语句。

    在调用 save() 方法之前,对对象所做的更改不会持久化到数据库中。

    4. 检索对象

    你已经知道如何使用 get() 方法从数据库中检索出一个对象。你使用 Post.objects.get()方法进行访问。每个 Django 模型至少有一个管理器,默认的管理器叫做 objects。你可以使用模型管理器获得 QuerySet 对象。从表中检索所有对象,只需在默认对象管理器上使用all()方法,就像这样:

    all_posts = Post.objects.all()

    这就是创建返回数据库中所有对象的QuerySet的方法,注意,这个时候查询集还没有执行。Django 的查询集是 延迟查询,也就是说,他们只有在被迫的时候才会被执行。这种方式可以使得QuerySet很有效率。如果没有将QuerySet设置为变量,而是直接在Python shell上编写它,则执行QuerySet的SQL语句,因为您强制它输出结果:

    >>> all_posts

    4.1. 使用 filter() 方法

    要过滤一个 QuerySets,你可以在管理器上中 filter() 方法。例如,您可以使用下面的QuerySet检索在2020年发布的所有文章:

    >>> Post.objects.filter(publish__year=2020)

    你也可以通过多个字段过滤,例如,你可以通过发布时间为 2020 年,作者为 admin 检索所有的文章。

    Post.objects.filter(publish__year=2020, author__username='admin' )

    使用字段查找方法的查询是使用两个下划线构建的,例如 publish__year, 但同样的符号也用于访问相关模型的字段,如 author__username。

    4.2. 使用 exclude()

    可以使用管理器的exclude()方法从QuerySet中排除某些结果。例如,您可以检索所有在2020年发布的文章,但标题不以Why开头:

    Post.objects.filter(publish__year=2020).exclude(title__startswith='Why')

    4.3. 使用 order_by()

    可以使用管理器的order_by()方法按不同的字段对结果进行排序。例如,您可以检索所有按标题排序的对象,如下:

    Post.objects.order_by('title')

    默认为升序,你可以使用 负号前缀 表明通过降序排序。如下所示:

    Post.objects.order_by('-title')

    5. 删除对象

    如果你想删除一个对象,你可以在实例对象上使用 delete() 方法。

    post = Post.objects.get(id=1)
    post.delete()
    

    注意,删除对象还将删除on_delete设置为CASCADE的外键对象的依赖关系。

    6. 在评估查询集时

    在对查询集进行计算之前,创建查询集不会涉及任何数据库活动。查询集通常返回一个没有计算的查询集,您可以将任意多的过滤连接到一个QuerySet,并且在QuerySet计算完成之前,您不会触及数据库,当计算一个查询集,它将转换为对数据库的 SQL 查询。

    查询集仅仅会在下面这些情况下被执行:

    • 第一次迭代它们的时候
    • 在对实例进行切片的时候。 Post.objects.all()[:3]
    • 当你pickle或缓存它们时。 (译者注: pickle 是序列化的意思)
    • 对他们调用 repr() 或者是 len() 方法时。
    • 对他们显式调用 list() 方法时。
    • 当您在语句(如bool()and, or, if)中测试它们时。

    7. 创建模型管理器

    正如前面说到的,objects是每个模型的默认管理器,它检索数据库中的所有对象,然而你可以可以为你的模型自定义一个管理器,您将创建一个自定义管理器来检索所有具有已发布状态的文章。

    有两种方法可以为你的模型添加或者定制一个管理器:1. 你可以对一个已存在的管理器添加额外的管理方法。2. 通过修改管理器返回状态来创建新的管理器。

    第一个方法为您提供了一个QuerySet API,比如 Post.objects.my_manager(), 第二种为您提供了 Post.my_manager.all()。这个管理器允许你通过使用 Post.published.all() 方法检索文章。

    在你的 blog 应用程序里面编写 models.py 文件去定制一个 管理器。

    class PublishedManager(models.Manager):
        def get_queryset(self):
            return super(PublishedManager, self).get_queryset().filter(status='published')
    
    class Post(models.Model):
        # .... 表示之前的代码
    
        objects = models.Manager()  # 默认管理器
        published = PublishedManager() # 我们定制的管理器
    

    模型中声明的第一个管理器成为默认管理器。你可以使用 Meta 属性 的 default_manager_name 来指定一个不同的默认理器。如果在Django模型中没有定义管理器。Django 会为它创建一个默认的管理器 objects。如果你为你的模型声明任何管理器,但是你想要保留 objects 管理器,你必须显式地将它添加到你的模型中。在前面的代码中,你添加了一个默认管理器objects 并且 还未 Post 模型定制了一个 published 管理器。

    管理器的 get_queryset() 方法返回将要执行的查询集。你可以重写此方法将您自定义的 filter 包含在最后的查询集中。

    现在您已经修改了自定义管理其并将其添加到 Post 模型中,你可以使用它执行查询。让我们来测试一下。

    使用以下的命令再次启动开发服务器:

    python manage.py shell

    现在你可以导入 Post 模型,并且检索所有标题前面是包含Who发布的文章,执行下面的查询集:

    from blog.models import Post
    Post.published.filter(title__startswith='Who')
    

    要获得这个查询集的结果,确保 在 Post 对象的 published 字段设置为 True, 并且 title 的开头是 Who.

    相关文章

      网友评论

          本文标题:1.5 使用查询集(QuerySets) 和 管理器(manag

          本文链接:https://www.haomeiwen.com/subject/njdykktx.html