翻译进度
3
分块数量
2
参与人数

Django ORM 和 QuerySets(查询集)

这是一篇协同翻译的文章,你可以点击『我来翻译』按钮来参与翻译。

《Django Girls》的 中文翻译 1.8 版本 已经翻译完成,请在参考 1.8 版本的基础上进行校正和翻译。


在这一章中,你将学习 Django 如何连接到数据库,并将数据存储在里面。让我们一探究竟吧!

QuerySet 是什么呢?

从本质上说,QuerySet 是给定模型的对象列表(list)。QuerySet 允许你从数据库中读取数据,对其进行筛选以及排序。

用例子来学习最容易的了。让我们试试这个,好吗?

Django shell

打开你本地的终端 (不是在 PythonAnywhere 上) 然后输入这个命令:

(myvenv) ~/djangogirls$ python manage.py shell

效果应该像这样:

(InteractiveConsole)
>>>

你现在在 Django 的交互式控制台中。它是就像 Python 提示符,但它有一些额外的 Django 魔法:blush:。你当然也可以在这里使用所有的 Python 命令。

所有对象( object )

首先让我们尝试显示所有我们的文章。你可以用下面的命令:

>>> Post.objects.all()
Traceback (most recent call last):
      File "<console>", line 1, in <module>
NameError: name 'Post' is not defined

哎呀 !出现了一个错误。它告诉我们没有文章。这是正确的 — — 我们忘了首先导入它 !

>>> from blog.models import Post

我们从 blog.models导入  Post  的模型。让我们试着再一次显示所有的文章:

>>> Post.objects.all()
<QuerySet [<Post: my post title>, <Post: another post title>]>

这是我们之前创建的文章的 list 列表!我们通过使用 Django admin 界面创建了这些文章。但是我们现在想通过 Python 来创建新的文章,那么我们应该如何做呢?

123wula 翻译于 19小时前

Create object

This is how you create a new Post object in database:

>>> Post.objects.create(author=me, title='Sample title', text='Test')

But we have one missing ingredient here: me. We need to pass an instance of User model as an author. How do we do that?

Let's import User model first:

>>> from django.contrib.auth.models import User

What users do we have in our database? Try this:

>>> User.objects.all()
<QuerySet [<User: ola>]>

This is the superuser we created earlier! Let's get an instance of the user now (adjust this line to use your own username):

>>> me = User.objects.get(username='ola')

As you can see, we now get a User with a username that equals 'ola'. Neat!

Now we can finally create our post:

>>> Post.objects.create(author=me, title='Sample title', text='Test')
<Post: Sample title>

Hurray! Wanna check if it worked?

>>> Post.objects.all()
<QuerySet [<Post: my post title>, <Post: another post title>, <Post: Sample title>]>

There it is, one more post in the list!

Add more posts

You can now have a little fun and add more posts to see how it works. Add two or three more and then go ahead to the next part.

Filter objects

A big part of QuerySets is the ability to filter them. Let's say we want to find all posts that user ola authored. We will use filter instead of all in Post.objects.all(). In parentheses we state what condition(s) a blog post needs to meet to end up in our queryset. In our case, the condition is that author should be equal to me. The way to write it in Django is author=me. Now our piece of code looks like this:

>>> Post.objects.filter(author=me)
<QuerySet [<Post: Sample title>, <Post: Post number 2>, <Post: My 3rd post!>, <Post: 4th title of post>]>

Or maybe we want to see all the posts that contain the word 'title' in the title field?

>>> Post.objects.filter(title__contains='title')
<QuerySet [<Post: Sample title>, <Post: 4th title of post>]>

There are two underscore characters (_) between title and contains. Django's ORM uses this rule to separate field names ("title") and operations or filters ("contains"). If you use only one underscore, you'll get an error like "FieldError: Cannot resolve keyword title_contains".

You can also get a list of all published posts. We do this by filtering all the posts that have published_date set in the past:

>>> from django.utils import timezone
>>> Post.objects.filter(published_date__lte=timezone.now())
<QuerySet []>

Unfortunately, the post we added from the Python console is not published yet. But we can change that! First get an instance of a post we want to publish:

>>> post = Post.objects.get(title="Sample title")

And then publish it with our publish method:

>>> post.publish()

Now try to get list of published posts again (press the up arrow key three times and hit enter):

>>> Post.objects.filter(published_date__lte=timezone.now())
<QuerySet [<Post: Sample title>]>

Ordering objects

QuerySets also allow you to order the list of objects. Let's try to order them by created_date field:

>>> Post.objects.order_by('created_date')
<QuerySet [<Post: Sample title>, <Post: Post number 2>, <Post: My 3rd post!>, <Post: 4th title of post>]>

We can also reverse the ordering by adding - at the beginning:

>>> Post.objects.order_by('-created_date')
<QuerySet [<Post: 4th title of post>,  <Post: My 3rd post!>, <Post: Post number 2>, <Post: Sample title>]>

Complex queries through method-chaining

As you saw, some methods on Post.objects return a QuerySet. The same methods can in turn also be called on a QuerySet, and will then return a new QuerySet. Thus, you can combine their effect by chaining them together:

>>> Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date')
<QuerySet [<Post: Post number 2>, <Post: My 3rd post!>, <Post: 4th title of post>, <Post: Sample title>]>

This is really powerful and lets you write quite complex queries.

Cool! You're now ready for the next part! To close the shell, type this:

>>> exit()
$

本文章首发在 LearnKu.com 网站上。

本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。

Summer
贡献者:2
讨论数量: 0
发起讨论 只看当前版本


暂无话题~