Useful Features of the Django Shell

The Django shell allows you to write Python statements from the command line as though they're being executed from within the Django Web Framework.

The Django shell is very powerful, but many beginner developers underestimate its utility.

This tutorial describes a few useful features of the Django shell.

Table of Contents

You can skip to a specific section of this Django shell tutorial using the table of contents below:

What is Django Shell

The Django shell is an interactive command-line interface shell environment that combines the Django framework functionality with the regular python shell. The Django shell loads the project-specific parameters and settings that only work within the project which allows the user to isolate the work environment and focus on that particular project.

One of the main functionality this shell provides is easy access to the object-relational mapper (ORM), which allows the user to directly interact with the database. The ORM is responsible for carrying out database queries within a Django project. The object-relational mapper reduces the need for extensive knowledge of relational databases and eliminates the need to use SQL queries within the project in most instances.

Accessing the Django Shell

The Django shell can be accessed using the shell command on a Django project. We will be using a standard Django project called “foodinventory” within the “food” python virtual environment throughout this article.

python manage.py shell

Before diving further into the Django shell we will create a Django app called “fruits” within the “foodinventory” project. Then populate the models.py by creating a “FruitsInfo” table and migrate the changes to create a simple SQLite Database.

python manage.py startapp fruits

models.py

from django.db import models

class FruitsInfo(models.Model):
    name = models.CharField(max_length=30)
    origin = models.CharField(max_length=60)
    price = models.DecimalField(max_digits=4,null=False,decimal_places=2)
    availability = models.IntegerField(default=0)

    def __str__(self):
            return self.origin + " " + self.name

.\foodinventory\settings.py

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'fruits'
]
python manage.py makemigrations

RESULT

python manage.py migrate

RESULT

Inserting Data into the Database

In Django, a model class represents a database table and an instance of that class represents a particular record within the database. This is analogous to using an INSERT statement in SQL. A record can be created simply by initiating the model class using the defined keyword arguments and calling the save() method to commit the new record to the database.

In the following example, we will look at how to add a new record to the FruitsInfo model class. First, we need to import the “FruitsInfo” class to the Django Shell then create an object of the “FruitsInfo” class called the record using all the keyword arguments and finally using the save() method to insert the record to the database.

from fruits.models import FruitsInfo  
record = FruitsInfo(name="apple",origin="USA",price=2.5,availability=1000)  
record.save()

RESULT

As there are no errors indicated in the Django shell, we can assume that the record was successfully added to the database. Let us verify this by using the “all()” method to call all the records from the database.

FruitsInfo.objects.all()

RESULT

Because we have defined a “__str__()” method to display an object in a human-readable format, the “all()” method will display only the value defined in the “__str__()” method. The value() method allows the users to extract the values of a given object as shown below.

FruitsInfo.objects.all().values()

RESULT

Another way to insert a record to a model class is to use the “create()” method. It eliminates the need to call the save() method to commit the record to the database.

from fruits.models import FruitsInfo  
record = FruitsInfo.objects.create(name="orange",origin="canada",price=1.25,availability=2000)

RESULT

Let us verify if the record was inserted into the database using the “all()” method.

FruitsInfo.objects.all().values()

RESULT

The above output shows us that the new record was created without the need to declare the “save()” method.

Inserting Multiple Records

In this section, we will look at how to insert multiple records to a specified class. We will create a new FruitsVendors class within models.py in the fruits app and migrate the changes.

Modified models.py file

from django.db import models

class FruitsInfo(models.Model):
    name = models.CharField(max_length=30)
    origin = models.CharField(max_length=60)
    price = models.DecimalField(max_digits=4,null=False,decimal_places=2)
    availability = models.IntegerField(default=0)

    def __str__(self):
            return self.origin + " " + self.name


class FruitsVendors(models.Model):
    vendor_id = models.CharField(max_length=4, null=False, primary_key=True)
    vendor_name = models.CharField(max_length=60)
    vendor_location = models.CharField(max_length=60)

    def __str__(self):
        return self.vendor_id + " - " + self.vendor_name + " - " + self.vendor_location

In the new FruitsVendors class, we have defined a primary key field named “vendor_id”. Then we defined the “str()” to display all the data within the class in a formatted string.

Migrating Changes

python manage.py makemigrations  
python manage.py migrate

RESULT

Let us look at how to insert multiple records to the FruitsVendors class at one using the bulk_create() method and the Django shell.

from fruits.models import FruitsVendors  
  
FruitsVendors.objects.bulk_create([FruitsVendors(vendor_id="V001", vendor_name="Fresh Fruits", vendor_location = "New York"), FruitsVendors(vendor_id="V002", vendor_name="Direct Delivery", vendor_location = "Sao Paulo"), FruitsVendors(vendor_id="V003", vendor_name="Fruit Mate", vendor_location = "Sydney"), ])

RESULT

Searching the Database

With the Django shell, we can search for objects within a database. When searching, we can use filters to extract specific objects. This is analogous to SELECT and WHERE statements in SQL. Let us look at how to search for records within the FruitsInfo class.

Searching for all objects

Using the all() method, we can obtain data for all the records within a table. If “str()” method is declared within the class, it will be the output of the all() method. To obtain the values within the object, we can append the values() method to the all() method.

from fruits.models import FruitsInfo  
FruitsInfo.objects.all()  
FruitsInfo.objects.all().values()

RESULT

Searching for a Single Record

The all() method with the filter can be used to retrieve a single record from a table. This is accomplished using the filter() method. The following examples demonstrate how to search for records by the id field and name field.

Search records by “id” integer field

from fruits.models import FruitsInfo  
FruitsInfo.objects.all().filter(id=1)

RESULT

FruitsInfo.objects.all().values().filter(id=1)

RESULT

Search records by “name” string field

FruitsInfo.objects.all().filter(name='orange')  
  
FruitsInfo.objects.all().values().filter(name='orange')

RESULTS

The filter() method will always return a Django QuerySet even if there is a single record in the output. If we wanted to retrieve a single record, we can use the get() method. However, if there is more than a single record that matches the query we specified within the get() method, this will result in a “MultipleObjectsReturned” error.

The get() method is most viable when we search using unique index fields such as the primary key. Let us see how the get method can be utilized using the “id” field.

record = FruitsInfo.objects.get(id=3)  
print(record)

RESULT

Retrieving specific data from a record

When using the get() method to retrieve a specific record, we can extract the information for a defined field using the new instance created while searching for the record. In the following example, we create a new instance called “record” for the FruitsInfo class where the “id” field is equal to “3”. Then we extract the information of each field.

record = FruitsInfo.objects.get(id=3)  
print(record)  
  
print(record.name)  
print(record.origin)  
print(record.price)  
print(record.availability)

RESULTS

Let us create a custom print statement using each field in the record

print(f"The stock of {record.name} which originates from {record.origin.title()} is at {record.availability} and each {record.name} is priced at {record.price}.")

RESULT

Field Lookups

In Django Object-Relational mapper, we can specify operators to further filter out the resulting dataset. This is analogous to the operators that can be specified within a SQL WHERE statement. Some example field lookups and their corresponding SQL operators are;

  • contains - LIKE
  • range - BETWEEN
  • gte (greater than or equal to) - >=
  • lte (less than or equal to) - <=

The following examples demonstrate how we can use the Field lookups from within the Django Shell

contains operator

Let us search for vendor names that include the name “Fruit” in the FruitsVendors class.

from fruits.models import FruitsVendors  
FruitsVendors.objects.filter(vendor_name__contains='Fruit')

RESULT

gte and lte operators

In the following examples, we will search for records where the price is greater than or equal to 2 and where the availability is less than or equal to 1000 in the FruitsInfo class.

from fruits.models import FruitsInfo  
FruitsInfo.objects.filter(price__gte=2)

RESULT

from fruits.models import FruitsInfo  
FruitsInfo.objects.filter(availability__lte=1000)

RESULT

Updating Records

The Object Manager provides a method called update() to update a single record or multiple records. When a successful update is done, the output will be the number of affected records within the database. The update() method is analogous to the UPDATE statement in SQL.

The following examples demonstrate how the update() method can be utilized.

Updating a Single Value

The update operation can be done along with a filter() method to specify the record that needs to be updated. Let us update the origin of the apples (id=1) in the FruitsInfo table.

from fruits.models import FruitsInfo  
record = FruitsInfo.objects.get(id=1)  
print(record.origin)  
  
FruitsInfo.objects.filter(id=1).update(origin='australia')  
  
record = FruitsInfo.objects.get(id=1)  
print(record.origin)

RESULT

From the above code block, we first check for the original value of the origin field of the record. Then we update the origin to “australia” and finally verify the update operation by calling the origin field using the get() method. As we have only updated a single record, the update operation outputs the number of records affected which is one.

Updating Multiple Values

In this section, we will take a look at how to update multiple fields within a record. To demonstrate this, we will be updating the price and availability field in the kiwi (id=4) record.

record = FruitsInfo.objects.get(id=4)  
print(f"Price = {record.price}, Availability = {record.availability}")  
  
FruitsInfo.objects.filter(id=4).update(price=0.55, availability=5000)  
  
record = FruitsInfo.objects.get(id=4)  
print(f"Price = {record.price}, Availability = {record.availability}")

RESULT

In the above code block, we have defined multiple fields that need to be updated within the update statement. The output of the update operation still signifies one because we have only updated multiple fields of a single record.

Updating Multiple Records

When updating multiple records, the main consideration is that the field that undergoes the update operation must be present within all the records. If the field is not available this will result in a FieldDoesNotExist error.

In the next example, we will update the availability field of all the records to 10000. we achieve this by using the update() method without specifying a filter.

FruitsInfo.objects.all().values()  
FruitsInfo.objects.update(availability=10000)  
FruitsInfo.objects.all().values()

RESULT

The output of the update operation shows us that there are four records affected by this update.

Deleting a Record

Django shell provides the delete() method to delete records from a specified class. This is analogous to the DELETE statement in SQL.

Deleting a single record

When deleting a single record we must use the get() method as it returns the specified object directly. Let us delete the kiwi (id=4) record from the FruitsInfo class.

FruitsInfo.objects.all().values()  
FruitsInfo.objects.get(id=4).delete()  
FruitsInfo.objects.all().values()

RESULT

The delete() method also outputs the number of records affected by the delete operation.

Deleting Multiple Records

The delete() method can be used to delete all the records within a given class by simply specifying the delete operation with the all() method. In the following example, we will delete all the remaining records from the FruitsInfo class.

FruitsInfo.objects.all().values()  
FruitsInfo.objects.all().delete()  
FruitsInfo.objects.all().values()

RESULT

From the above output, we can identify that the delete operation is carried out on all the remaining three records.

Final Thoughts

In this article, we learned how to use the Django Shell to interact with the database using the Django Object Relational Mapper. The Django Shell provides all the functionality of the standard python shell while adding the functionality of the Django framework directly to the shell environment. This enables developers to test and debug database interactions without the need to modify the Django project.

If you enjoyed this article, be sure to join my Developer Monthly newsletter, where I send out the latest news from the world of Python and JavaScript:


Written on October 24th, 2020