As we have created the necessary database tables for the book review application, let’s work on understanding the basic database operations with Django.
We’ve already briefly touched on database operations using SQL statements in the SQL CRUD operations section. We tried creating an entry in the database using the insert
statement, read from the database using the select
statement, updated an entry using the update
statement, and deleted an entry from the database using the delete
statement.
Django’s ORM provides the same functionality without having to deal with SQL statements. Django’s database operations are simple Python code, hence we overcome the hassle of maintaining SQL statements among the Python code. Let’s take a look at how these are performed.
To execute the CRUD operations, we will enter Django’s command-line shell by executing the following command:
python manage.py shell
Note
For this chapter, we will designate Django shell commands using the >>>
notation (highlighted) at the start of the code block. When pasting the query into DB Browser, make sure you exclude this notation every time.
When the interactive console starts, it looks as follows:
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>>
In the following exercise, we shall perform a create operation.
Exercise 2.02 – creating an entry in the bookr database
In this exercise, you will create a new entry in the database by saving a model instance. In other words, you will create an entry in a database table without explicitly running a SQL query. Follow these steps to do this:
- First, import the
Publisher
class/model from reviews.models
:>>> from reviews.models import Publisher
- Create an object or an instance of the
Publisher
class by passing all the field values (name
, website
, and email
) required by the Publisher
model:>>> publisher = Publisher(name='Packt Publishing',
website='https://www.packtpub.com',
email='info@packtpub.com')
- Next, to write the object into the database, it is important to call the
save()
method, because until this is called, the entry will not be created in the database:>>> publisher.save()
Now you can see a new entry created in the database using DB Browser:
Figure 2.19: An entry created in the database
- Use the object attributes to make any further changes to the object and save the changes to the database:
>>> publisher.email = 'info@packtpub.com'
>>> publisher.email = 'customersupport@packtpub.com'
>>> publisher.save()
You can see the changes using DB Browser as follows:
Figure 2.20: An entry with the updated email field
In this exercise, we created an entry in the database by creating an instance of the model object and used the save()
method to write the model object into the database.
Note that by following the preceding method, the changes to the class instance are not saved until the save()
method is called. However, if we use the create()
method, Django saves the changes to the database in a single step. We’ll use this method in the exercise that follows.
Exercise 2.03 – using the create() method to create an entry
Unlike the previous exercise where we executed two separate steps by first creating an object and later using the save()
method to create an entry in the database, in this exercise, you will create a record in the contributor
table using the create()
method in a single step:
- First, import the
Contributor
class as before:>>> from reviews.models import Contributor
- Invoke the
create()
method to create an object in the database in a single step. Ensure that you pass all the required parameters (first_names
, last_names
, and email
):>>> contributor =
Contributor.objects.create(first_names="Rowel",
last_names="Atienza",
email="RowelAtienza@example.com")
- Use DB Browser to verify that the contributor record has been created in the database. If DB Browser is not already open, open the
db.sqlite3
database file as we just did in the previous section. Click Browse Data and select the desired table – in this case, the reviews_contributor
table from the Table drop-down menu, as shown in the screenshot – and verify the newly created database record:
Figure 2.21: Verifying the creation of the record in DB Browser
In this exercise, we learned that using the create()
method, we can create a record for a model in a database in a single step.
Creating an object with a foreign key
Similar to how we created a record in the Publisher
and Contributor
tables, let’s now create one for the Book
table. If you recall, the Book
model has a foreign key to Publisher
that cannot have a null value. So, a way to populate the publisher’s foreign key is by providing the created publisher
object in the book’s publisher
field as shown in the following exercise.
Exercise 2.04 – creating records for a many-to-one relationship
In this exercise, you will create a record in the Book
table, including a foreign key to the Publisher
model. As you already know, the relationship between Book
and Publisher
is a many-to-one relationship, so you have to first fetch the Publisher
object and then use it while creating the book record. To do that, follow these steps:
- First, import the
Publisher
class:>>> from reviews.models import Book, Publisher
- Retrieve the
publisher
object from the database using the following command. The get()
method is used to retrieve an object from the database. We still haven’t explored database read operations. For now, use the following command; we will go deeper into reading/retrieving from databases in the next section: >>> publisher =
Publisher.objects.get(name='PacktPublishing')
- When creating a book, we need to supply a
date
object, as publication_date
is a date field in the Book
model. So, import date
from datetime
so that a date
object can be supplied when creating the book
object, as shown in the following code:>>> from datetime import date
- Use the
create()
method to create a record of the book in the database. Ensure that you pass all the fields, namely title
, publication_date
, isbn
, and the publisher
object:>>> book = Book.objects.create(title="Advanced Deep
Learning with Keras", publication_date=date(2018,
10, 31), isbn="9781788629416",
publisher=publisher)
Note that since publisher
is a foreign key and it is not nullable (cannot hold a null
value), it is mandatory to pass a publisher
object. When the mandatory foreign key object, publisher
, is not provided, the database will throw an integrity error.
Figure 2.22 shows the Book
table where the first entry is created. Notice that the foreign key field (publisher_id
) points to the id
value
(primary key) of the Publisher
table. The publisher_id
entry in the book’s record points to a Publisher
record has a primary key of 1
, as shown in the following two screenshots:
Figure 2.22: Foreign key pointing to the primary key for reviews_book
Figure 2.23: Foreign key pointing to the primary key for reviews_publisher
In this exercise, we learned that when creating a database record, an object can be assigned to a field if it is a foreign key. We know that the Book
model also has a many-to-many relationship with the Contributor
model. Let’s now explore the ways to establish many-to-many relations as we create records in the database.
Exercise 2.05 – creating records with many-to-many relationships
In this exercise, you will create a many-to-many relationship between Book
and Contributor
using the BookContributor
relationship model:
- In case you have restarted the shell and lost the
publisher
and book
objects, retrieve them from the database by using the following set of Python statements:>>> from reviews.models import Book
>>> from reviews.models import Contributor
>>> contributor =
Contributor.objects.get(first_names='Rowel')
>>> book = Book.objects.get(title="Advanced Deep
Learning with Keras")
- The way to establish a many-to-many relationship is by storing the information about the relationship in the intermediary model or the relationship model; in this case,
BookContributor
. Since we have already fetched the book and the contributor records from the database, let’s use these objects when creating a record for the BookContributor
relationship model. To do so, first, create an instance of the BookContributor
relationship class and then save the object to the database. While doing so, ensure you pass the required fields, namely the book
object, the contributor
object, and role
:>>> from reviews.models import BookContributor
>>> book_contributor = BookContributor(book=book,
contributor=contributor, role='AUTHOR')
>>> book_contributor.save()
Notice that we set role to AUTHOR
while creating the book_contributor
object. This is a classic example of storing relationship data while establishing a many-to-many relationship. The role can be AUTHOR
, CO_AUTHOR
, or EDITOR
.
This established the relationship between the book Advanced Deep Learning with Keras and the contributor Rowel (Rowel being the author of the book).
In this exercise, we established a many-to-many relationship between Book
and Contributor
using the BookContributor
relationship model. With regards to the verification of the many-to-many relationship that we just created, we will see this in detail in a few exercises later on in this chapter.
Exercise 2.06 – a many-to-many relationship using the add() method
In this exercise, you will establish a many-to-many relationship using the add()
method. When we don’t use a relationship to create the objects, we can use through_default
to pass in a dictionary with the parameters defining the required fields. Continuing from the previous exercise, let’s add one more contributor to the book titled Advanced Deep Learning with Keras. This time, the contributor is an editor of the book:
- If you have restarted the shell, run the following two commands to import and fetch the desired
book
instance:>>> from reviews.models import Book, Contributor
>>> book = Book.objects.get(title="Advanced Deep
Learning with Keras")
- Use the
create()
method to create a contributor, as shown here:>>> contributor =
Contributor.objects.create(first_names='Packt',
last_names='Example Editor',
email='PacktEditor@example.com')
- Add the newly created contributor to the book using the
add()
method. Ensure you provide the role
relationship parameter as dict
. Enter the following code:>>> book.contributors.add(contributor,
through_defaults={'role': 'EDITOR'})
Thus, we used the add()
method to establish a many-to-many relationship between the book and the contributor while storing the relationship data role as EDITOR
. Let’s now take a look at other ways of doing this.
Using the create() and set() methods for many-to-many relationships
Assume the book Advanced Deep Learning with Keras has a total of two editors. Let’s use the following method to add another editor to the book. If the contributor is not already present in the database, then we can use the create()
method to simultaneously create an entry as well as to establish its relationship with the book:
>>> book.contributors.create(first_names='Packtp',
last_names='Editor Example',
email='PacktEditor2@example.com',
through_defaults={'role': 'EDITOR'})
Similarly, we can also use the set()
method to add a list of contributors for a book. Let’s create a publisher, a set of two contributors who are the co-authors, and a book
object. First, import the Publisher
model, if not already imported, using the following code:
>>> from reviews.models import Publisher
The following code will help us do so:
>>> publisher =
Publisher.objects.create(name='Pocket Books',
website='https://pocketbookssampleurl.com',
email='pocketbook@example.com')
>>> contributor1 =
Contributor.objects.create(first_names='Stephen',
last_names='Stephen', email='StephenKing@example.com')
>>> contributor2 =
Contributor.objects.create(first_names='Peter',
last_names='Straub', email='PeterStraub@example.com')
>>> book = Book.objects.create(title='The Talisman',
publication_date=date(2012, 9, 25),
isbn='9781451697216', publisher=publisher)
Since this is a many-to-many relationship, we can add a list of objects in just one go using the set()
method. We can use through_defaults
to specify the role of the contributors; in this case, they are co-authors:
>>> book.contributors.set([contributor1, contributor2],
through_defaults={'role': 'CO_AUTHOR'})
Read operations
Django provides us with methods that allow us to read/retrieve from the database. We can retrieve a single object from the database using the get()
method. We have already created a few records in the previous sections, so let’s use the get()
method to retrieve an object.
Exercise 2.07 – using the get() method to retrieve an object
In this exercise, you will retrieve an object from the database using the get()
method. Follow these steps:
- Fetch a
Publisher
object that has a name
field of Pocket Books
:>>> from reviews.models import Publisher
>>> publisher =
Publisher.objects.get(name='Pocket Books')
- Re-enter the retrieved
publisher
object and press Enter:>>> publisher
<Publisher: Pocket Books>
Notice that the output is displayed in the shell. This is called a string representation of an object. It is the result of adding the __str__()
model method as we did in the Model methods section for the Publisher
class.
- Upon retrieving the object, you have access to all the object’s attributes. Since this is a Python object, the attributes of the object can be accessed by using
.
followed by the attribute name. So, you can retrieve the publisher’s name with the following command:>>> publisher.name
'Pocket Books'
- Similarly, to retrieve the publisher’s website, use the following:
>>> publisher.website
'https://pocketbookssampleurl.com'
The publisher’s email address can be retrieved as follows:
>>> publisher.email
'pocketbook@example.com'
In this exercise, we learned how to fetch a single object using the get()
method. There are several disadvantages to using this method, though. Let’s find out what they are next.
Returning an object using the get() method
It is important to note that the get()
method can only fetch one object. If there is another object carrying the same value as the field mentioned, then we can expect a returned more than one error message. For example, if there are two entries in the Publisher
table with the same value for the name
field, we can expect an error. In such cases, there are alternate ways to retrieve those objects, which we will explore in the subsequent sections.
We can also get a matching query does not exist error message when there are no objects returned by the get()
query. The get()
method can be used with any of the object’s fields to retrieve a record. In the following case, we use the website
field:
>>> publisher =
Publisher.objects.get(
website='https://pocketbookssampleurl.com')
After retrieving the object, we can still get the publisher’s name, as shown here:
>>> publisher.name
'Pocket Books'
Another way to retrieve an object is by using its primary key, pk
, as can be seen here:
>>> Publisher.objects.get(pk=2)
<Publisher: Pocket Books>
Using pk
for the primary key is a more generic way of using the primary key field. But for the Publisher
table, since we know that id
is the primary key, we can simply use the id
field name to create our get()
query:
>>> Publisher.objects.get(id=2)
<Publisher: Pocket Books>
Note
For Publisher
and all the other tables, the primary key is id
, which Django automatically created. This happens when a primary key field is not mentioned at the time of the creation of the table. But there can be instances where a field can be explicitly declared as a primary key.
In the next exercise, we will see how to query and retrieve all the objects for a given model.
Exercise 2.08 – using the all() method to retrieve a set of objects
We can use the all()
method to retrieve a set of all objects. In this exercise, you will use this method to retrieve the names of all contributors. To do that, follow these steps:
- Add the following code to retrieve all the objects from the
Contributor
table:>>> from reviews.models import Contributor
>>> Contributor.objects.all()
<QuerySet [<Contributor: Rowel>, <Contributor: Packt>, <Contributor: Packtp>, <Contributor: Stephen>, <Contributor: Peter>]>
Upon execution, you will get QuerySet
of all the objects.
- We can use list indexing to look up a specific object or to iterate over the list using a loop to do any other operation:
>>> contributors = Contributor.objects.all()
- Since
Contributor
is a list of objects, you can use indexing to access any element in the list, as shown in the following command:>>> contributors[0]
<Contributor: Rowel>
In this case, the first element in the list is a contributor with a first_names
value of 'Rowel'
and a last_names
value of 'Atienza'
, as you can see from the following code:
>>> contributors[0].first_names
'Rowel'
>>> contributors[0].last_names
'Atienza'
In this exercise, we learned how to retrieve all the objects using the all()
method and how to use the retrieved set of objects as a list.
Retrieving objects by filtering
If we have more than one object for a field value, we cannot use the get()
method since the get()
method can return only one object. For such cases, we have the filter()
method, which can retrieve all the objects that match a specified condition.
Exercise 2.09 – using the filter() method to retrieve objects
In this exercise, you will use the filter()
method to get a specific set of objects for a certain condition. Specifically, you will retrieve all the contributors’ names whose first name is Peter
. To do that, follow these steps:
- First, create two more contributors:
>>> from reviews.models import Contributor
>>> Contributor.objects.create(first_names='Peter',
last_names='Wharton',
email='PeterWharton@example.com')
>>> Contributor.objects.create(first_names='Peter',
last_names='Tyrrell',
email='PeterTyrrell@example.com')
- To retrieve contributors who have the
first_names
value of Peter
, add the following code:>>> Contributor.objects.filter(first_names='Peter')
<QuerySet [<Contributor: Peter>, <Contributor: Peter>,
<Contributor: Peter>]>
- The
filter()
method returns the object even if there is only one. You can see this here:>>> Contributor.objects.filter(first_names='Rowel')
<QuerySet [<Contributor: Rowel>]>
- Furthermore, the
filter()
method returns an empty QuerySet
if nothing matches the query. This can be seen here:>>> Contributor.objects.filter(first_names='Nobody')
<QuerySet []>
In this exercise, we saw the use of filters to retrieve a set of a few objects filtered by a certain condition. In the next section, we will learn about filtering by using field lookups.
Filtering by field lookups
Now, let’s suppose we want to filter and query a set of objects using the object’s fields by providing certain conditions. In such a case, we can use a double-underscore lookup. For example, the Book
object has a publication_date
field; let’s say we want to filter and fetch all the books that were published after 01-01-2014. We can easily look these up by using the double-underscore method. To do this, we will first import the Book
model:
>>> from reviews.models import Book
>>> book = Book.objects.filter(publication_date__gt=date(
2014, 1, 1))
Here, publication_date__gt
indicates the publication date, which is greater than (gt
) a certain specified date, in this case, 01-01-2014. Similar to this, we have the following abbreviations:
lt
: Less than
lte
: Less than or equal to
gte
: Greater than or equal to
The result after filtering can be seen here:
>>> book
<QuerySet [<Book: Advanced Deep Learning with Keras>]>
Here is the publication date of the book that is part of the query set, which confirms that the publication date was after 01-01-2014:
>>> book[0].publication_date
datetime.date(2018, 10, 31)
Using pattern matching for filtering operations
For filtered results, we can also look up whether the parameter contains a part of the string we are looking for:
>>> book =
Book.objects.filter(title__contains='Deep learning')
Here, title__contains
looks for all objects with titles containing 'Deep learning'
as a part of the string:
>>> book
<QuerySet [<Book: Advanced Deep Learning with Keras>]>
>>> book[0].title
'Advanced Deep Learning with Keras'
Similarly, we can use icontains
if the string match needs to be case-insensitive. Using startswith
matches any string starting with the specified string.
Retrieving objects by using the exclude() method
In the previous section, we learned about fetching a set of objects by matching a certain condition. Now, suppose we want to do the opposite; that is, we want to fetch all those objects that do not match a certain condition. In such cases, we can use the exclude()
method to exclude a certain condition and fetch all the required objects. This will be clearer with an example. The following is a list of all contributors:
>>> Contributor.objects.all()
<QuerySet [<Contributor: Rowel>, <Contributor: Packt>,
<Contributor: Packtp>, <Contributor: Stephen>,
<Contributor: Peter>, <Contributor: Peter>,
<Contributor: Peter>]>
Now, from this list, we will exclude all those contributors who have a first_names
value of Peter
:
>>> Contributor.objects.exclude(first_names='Peter')
<QuerySet [<Contributor: Rowel>, <Contributor: Packt>,
<Contributor: Packtp>, <Contributor: Stephen>]>
We see here that the query returned all contributors whose first name is not Peter.
Retrieving objects using the order_by() method
We can retrieve a list of objects while ordering by a specified field using the order_by()
method. For example, in the following code snippet, we order the books by their publication date:
>>> books = Book.objects.order_by("publication_date")
>>> books
<QuerySet [<Book: The Talisman>, <Book: Advanced Deep Learning with Keras>]>
Let’s examine the order of the query. Since the query set is a list, we can use indexing to check the publication date of each book:
>>> books[0].publication_date
datetime.date(2012, 9, 25)
>>> books[1].publication_date
datetime.date(2018, 10, 31)
Notice that the publication date of the first book with a 0
index is older than the publication date of the second book with a 1
index. So, this confirms that the queried list of books has been properly ordered as per their publication dates. We can also use a prefix with the negative sign for the field parameter to order results in descending order. This can be seen from the following code snippet:
>>> books = Book.objects.order_by("-publication_date")
>>> books
<QuerySet [<Book: Advanced Deep Learning with Keras>,
<Book: The Talisman>]>
Since we have prefixed a negative sign to the publication date, notice that the queried set of books has now been returned in the opposite order, where the first book object with a 0
index has a more recent date than the second book:
>>> books[0].publication_date
datetime.date(2018, 10, 31)
>>> books[1].publication_date
datetime.date(2012, 9, 25)
We can also order by using a string field or a numerical one. For example, the following code can be used to order books by their primary key or id
:
>>> books = Book.objects.order_by('id')
>>> books
<QuerySet [<Book: Advanced Deep Learning with Keras>,
<Book: The Talisman>]>
The queried set of books has been ordered by book id
in ascending order:
>>> books[0].id
1
>>> books[1].id
2
Again, to order it in descending order, the negative sign can be used as a prefix, as follows:
>>> books = Book.objects.order_by('-id')
>>> books
<QuerySet [<Book: The Talisman>, <Book: Advanced Deep Learning with Keras>]>
Now, the queried set of books has been ordered by book id
in descending order:
>>> books[0].id
2
>>> books[1].id
1
To order by a string field in alphabetical order, we can do something like this:
>>> books = Book.objects.order_by('title')
>>> books
<QuerySet [<Book: Advanced Deep Learning with Keras>, <Book: The Talisman>]>
Since we have used the title of the book to order by, the query set has been ordered in alphabetical order. We can see this as follows:
>>> books[0]
<Book: Advanced Deep Learning with Keras>
>>> books[1]
<Book: The Talisman>
Similar to what we’ve seen for the previous ordering types, the negative sign prefix can help us sort in reverse alphabetical order, as we can see here:
>>> books = Book.objects.order_by('-title')
>>> books
<QuerySet [<Book: The Talisman>, <Book: Advanced Deep Learning with Keras>]>
This will lead to the following output:
>>> books[0]
<Book: The Talisman>
>>> books[1]
<Book: Advanced Deep Learning with Keras>
Yet another useful method offered by Django is values()
. It helps us get a query set of dictionaries instead of objects. In the following code snippet, we’re using this for a Publisher
object:
>>> publishers = Publisher.objects.all().values()
>>> publishers
<QuerySet [{'id': 1, 'name': 'Packt Publishing', 'website':
'https://www.packtpub.com', 'email':
'customersupport@packtpub.com'}, {'id': 2, 'name':
'Pocket Books', 'website':
'https://pocketbookssampleurl.com',
'email': 'pocketbook@example.com'}]>
>>> publishers[0]
{'id': 1, 'name': 'Packt Publishing', 'website':
'https://www.packtpub.com', 'email':
'customersupport@packtpub.com'}
>>> publishers[0]
{'id': 1, 'name': 'Packt Publishing', 'website':
'https://www.packtpub.com', 'email':
'customersupport@packtpub.com'}
In the next few sections, we will explore how to query across relationships.
Querying across relationships
As we have studied in this chapter, the reviews
app has two kinds of relationships: many-to-one and many-to-many. So far, we have learned various ways of making queries using get()
, filters, field lookups, and so on. Now let’s study how to perform queries across relationships. There are several ways to go about this – we could use foreign keys, object instances, and more. Let’s explore these with the help of some examples.
Querying using foreign keys
When we have relationships across two models/tables, Django provides a way to perform a query using the relationship. The command shown in this section will retrieve all the books published by Packt Publishing
by performing a query using model relationships. Similar to what we’ve seen previously, this is done using the double-underscore lookup. For example, the Book
model has a foreign key of publisher
pointing to the Publisher
model. Using this foreign key, we can perform a query using double underscores and the name
field in the Publisher
model. This can be seen from the following code:
>>> Book.objects.filter(publisher__name='Packt Publishing')
<QuerySet [<Book: Advanced Deep Learning with Keras>]>
Querying using the model name
Another way of querying is using a relationship to do the query backward, using the model name in lowercase. For instance, let’s say we want to query the publisher who published the book Advanced Deep Learning with Keras using model relationships in the query. For this, we can execute the following statement to retrieve the Publisher
information object:
>>> Publisher.objects.get(book__title='Advanced Deep
Learning with Keras')
<Publisher: Packt Publishing>
Here, book
is the model’s name in lowercase. As we already know, the Book
model has a publisher
foreign key with a name
value of Packt Publishing
.
Querying across foreign key relationships using the object instance
We can also retrieve the information using the object’s foreign key. Suppose we want to query the publisher’s name for the title The Talisman:
>>> book = Book.objects.get(title='The Talisman')
>>> book.publisher
<Publisher: Pocket Books>
Using the object here is an example of where we use the reverse direction to get all the books published by a publisher by using the set.all()
method:
>>> publisher = Publisher.objects.get(name='Pocket Books')
>>> publisher.book_set.all()
<QuerySet [<Book: The Talisman>]>
We can also create queries using chains of queries:
>>> Book.objects.filter(publisher__name='Pocket
Books').filter(title='The Talisman')
<QuerySet [<Book: The Talisman>]>
Let’s perform some more exercises to shore up our knowledge of the various kinds of queries we have learned about so far.
Exercise 2.10 – querying across a many-to-many relationship using the field lookup
We know that Book
and Contributor
have a many-to-many relationship. In this exercise, without creating an object, you will perform a query to retrieve all the contributors who contributed to writing the book titled The Talisman:
- First, import the
Contributor
class:>>> from reviews.models import Contributor
- Now, add the following code to query for the set of contributors to The Talisman:
>>> Contributor.objects.filter(book__title='The
Talisman')
You should see the following:
<QuerySet [<Contributor: Stephen>, <Contributor: Peter>]>
From the preceding output, we can see that Stephen
and Peter
are the contributors who contributed to writing the book The Talisman. The query uses the book
model (written in lowercase) and does a field lookup for the title
field using a double underscore, as shown in the command.
In this exercise, we learned how to perform queries across many-to-many relationships using a field lookup. Let’s now look at using another method to carry out the same task.
Exercise 2.11 – a many-to-many query using objects
In this exercise, using a Book
object, search for all the contributors who contributed to writing the book with the title The Talisman. The following steps will help you do that:
- Import the
Book
model:>>> from reviews.models import Book
- Retrieve a
book
object with the title The Talisman, by adding the following line of code:>>> book = Book.objects.get(title='The Talisman')
- Then, retrieve all the contributors who worked on the book The Talisman using the
book
object. Add the following code to do so:>>> book.contributors.all()
<QuerySet [<Contributor: Stephen>, <Contributor: Peter>]>
Again, we can see that Stephen
and Peter
are the contributors who worked on the book The Talisman. Since the book has a many-to-many relationship with contributors, we have used the contributors.all()
method to get a query set of all those contributors who worked on the book. Now, let’s try using the set()
method to perform a similar task.
Exercise 2.12 – a many-to-many query using the set() method
In this exercise, you will use a contributor
object to fetch all the books written by the contributor named Rowel
:
- Import the
Contributor
model:>>> from reviews.models import Contributor
- Fetch a
contributor
object whose first_names
is 'Rowel'
using the get()
method:>>> contributor =
Contributor.objects.get(first_names='Rowel')
- Using the
contributor
object and the book_set()
method, get all those books written by the contributor:>>> contributor.book_set.all()
<QuerySet [<Book: Advanced Deep Learning with Keras>]>
Since Book
and Contributor
have a many-to-many relationship, we can use the set()
method to query a set of objects associated with the model. In this case, contributor.book_set.all()
returned all the books written by the contributor.
Exercise 2.13 – using the update() method
In this exercise, you will use the update()
method to update an existing record:
- Change
first_names
for a contributor who has the last name Tyrrell
:>>> from reviews.models import Contributor
>>> Contributor.objects.filter(last_names='Tyrrell').
update(first_names='Mike')
1
The return value shows the number of records that have been updated. In this case, one record has been updated.
- Fetch the contributor that was just modified using the
get()
method and verify that the first name has been changed to Mike
:>>> Contributor.objects.get(last_names='Tyrrell').
first_names
'Mike'
Note
If the filter operation has more than one record, then the update()
method will update the specified field in all the records returned by the filter.
In this exercise, we learned how to use the update()
method to update a record in the database. Now, finally, let’s try deleting a record from the database using the delete()
method.
Exercise 2.14 – using the delete() method
An existing record in the database can be deleted using the delete()
method. In this exercise, you will delete a record from the contributors
table that has the last_name
value of Wharton
:
- Fetch the object using the
get()
method and use the delete()
method, as shown here:>>> from reviews.models import Contributor
>>> Contributor.objects.get(last_names='Wharton').
delete()
(1, {'reviews.Contributor': 1}
Notice that you called the delete()
method without assigning the contributor
object to a variable. Since the get()
method returns a single object, you can access the object’s method without actually creating a variable for it.
- Verify the
contributor
object with last_name
as 'Wharton'
has been deleted:>>> Contributor.objects.get(last_names='Wharton')
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/../site-packages/django/db/models/manager.py",
line 82, in manager_method
return getattr(self.get_queryset(), name)(*args,
**kwargs)
File "/../site-packages/django/db/models/query.py",
line 417, in get
self.model._meta.object_name
reviews.models.Contributor.DoesNotExist: Contributor
matching query does not exist.
As you can see, upon running the query, we got an object does not exist error. This is expected since the record has been deleted. In this exercise, we learned how to use the delete()
method to delete a record from the database.