Django ORM and QuerySets

Part of this chapter is based on tutorials by Django Girls Tutorial : https://tutorial.djangogirls.org

In this chapter you'll learn how Django connects to the database and stores data in it. Let's dive in!

What is a QuerySet?

A QuerySet is, in essence, a list of objects of a given Model. QuerySets allow you to read the data from the database, filter it and order it. It's easiest to learn by example. Let's try this, shall we?

Django shell

Open up your console and type this command:

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

Something similar to the following would be displayed in your console:

Python 3.6.2 (v3.6.2:5fd33b5926, Jul 16 2017, 20:11:06) 
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>>

You're now in Django's interactive console. It's just like the Python prompt, but with some additional Django magic. :) You can use all the Python commands here too, of course.

All objects

Let's try to display all of our player entries first. You can do that with the following command in the Django shell:

>>> Player.objects.all()

Oops! An error showed up. It tells us that there is no Player. It's correct – we forgot to import it first!

>>> from myfirstgame.models import Player

We import the model Player from myfirstgame.models. Let's try displaying all player entries again:

>>> Player.objects.all()
<QuerySet [<Player: vicky>, <Player: whykiki>, <Player: whyknot>]>

This is a list of the player entries we created earlier! We created these entries using the Django admin interface. But now we want to create new player entries using Python, so how do we do that?

Create object

This is how you create a new Player object in database with Python:

>>> Player.objects.create(name="Janette")

Hurray! Wanna check if it worked?

>>> Player.objects.all()
<QuerySet [<Player: vicky>, <Player: whykiki>, <Player: whyknot>, <Player: Janette>]>

Add more players

You can now have a little fun and add more player entries 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 players that user vicky authored. We will usefilterinstead ofallin Player.objects.all(). In parentheses we state what condition(s) a player entry needs to meet to end up in our queryset.

In our case, the condition is that name should be equal to vicky. The way to write it in Django is name="vicky". Now our piece of code looks like this:

>>> Player.objects.filter(name="vicky")
<QuerySet [<Player: vicky>]>

Or maybe we want to see all the player entries that contain the word 'why' in the name field?

>>> Player.objects.filter(name__contains="why")
<QuerySet [<Player: whykiki>, <Player: whyknot>]>

There are two underscore characters (_) between name and contains. Django's ORM uses this rule to separate field names ("name") 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 players. We do this by filtering all the players that have game_end set in the past:

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

Unfortunately, the entry we added from the Python console is does not have a game ended date yet. But we can change that! First get an instance of a player we want to publish:

>>> player = Player.objects.get(name="whykiki")
>>> player
<Player: whykiki>
>>> player.gameover()
>>> Player.objects.filter(game_end__lte=timezone.now())
<QuerySet [<Player: whykiki>]>

Ordering objects

QuerySets also allow you to order the list of objects. Let's try to order them by endgame (datetime) field:

>>> Player.objects.order_by('game_end')
<QuerySet [<Player: vicky>, <Player: whykiki>, <Player: whyknot>, <Player: Janette>]>

Chaining QuerySets

You can also combine QuerySets by chaining them together:

>>> Player.objects.filter(game_end__lte=timezone.now()).order_by("game_end")
<QuerySet [<Player: whykiki>]>

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()
(myvenv) ~/textbasedgame$

results matching ""

    No results matching ""