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.