How to delete an object in Django

Key takeaways:

  • Deleting elements from a Django application's database can be done in two different deletion methods while keeping our database consistent.

    • Hard delete: Suitable for permanently deleting specific objects from the database.

    • Soft delete: Good for eliminating records in a way that keeps them in the database while making them unavailable to users.

  • For hard delete, use the delete() function directly and for soft delete, create a custom base model with an is_deleted flag.

Django is an open-source web framework based on Python that enables the rapid development of database-driven applications by offering a clean and organized structure. It simplifies the implementation of repetitive tasks, freeing developers to concentrate on application logic rather than dealing with unnecessary boilerplate code. Through Django’s robust Object-Relational Mapping (ORM) system, developers can efficiently perform operations such as inserting, updating, and deleting data in the connected database. The ORM translates Python code into SQL queries, abstracting the underlying database interactions.

Deleting an element from a Django application’s database can be risky. This Answer will guide readers on implementing two different deletions while our database remains consistent. 

Two different deletions are:

  • Hard delete

  • Soft delete 

Hard delete

Hard deletion is the procedure of permanently removing particular objects from the database. For this purpose, the delete() function of the object’s class is invoked to delete an object. This results in the object being deleted from the database with no possibility of recovery.

Pros of hard delete

It’s easy to implement. There is no need to keep track of deleted records. It may reduce the database size.

Cons of hard delete

Retrieving deleted data becomes impossible. Executing a delete() command for hard deletion tends to be slower, especially with interconnected records across tables.

Implementation of hard delete

Let's start with creating the Django application. For this purpose, the following commands will create a Django project in first_project directory; then, we will create a new Django application name first_app to implement the delete functionality.

django-admin startproject first_project
cd first_project && python3 manage.py startapp first_app
Create Django application name as "first_app"

Open the settings.py file in first_project folder and add first_app string under the INSTALLED_APPS and save the file.

# settings.py
# Application definition
INSTALLED_APPS = [
#existing apps
'first_app'
]
Defining application

Now, define a Student model in the models.py file of our application.

#models.py
from django.db import models
class Student(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
email = models.EmailField(unique=True)
roll_no = models.CharField(max_length=100)
degree = models.CharField(max_length=100)
Student class in models.py

This creates a table in SQLite with the table name, Student, and the attributes first_name, last_name, email, roll_no, and degree. The table will be created once we run the migrate and makemigrations commands on the shell. Run migrations to apply changes to the database, then use the migrations.

python3 manage.py makemigrations
python3 manage.py migrate
Commands to run migrations

We create a file like create_students.py to show how to store some Student objects in the database.

# create_students.py
import os
import sys
import django
# Set up Django environment
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'first_project.settings')
django.setup()
# Import the Student model
from first_app.models import Student
def main():
# Create Student objects and set their attributes
student1 = Student(first_name='Alice', last_name='Zoe', email='alice.zoe@example.com', roll_no='SE_123', degree='SE')
student2 = Student(first_name='Tom', last_name='Smith', email='tom.smith@example.com', roll_no='CS_123', degree='CS')
student3 = Student(first_name='Bethy', last_name='Gorden', email='bethy.gorden@example.com', roll_no='CS_456', degree='CS')
# Save the Student objects to the database
student1.save()
student2.save()
student3.save()
print("Students created successfully.")
# Call the main function
if __name__ == "__main__":
main()
create_students.py

We create a file like delete_students.py to show how to delete the second Student object in the database.

# delete_students.py
import os
import sys
import django
# Set up Django environment
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'first_project.settings')
django.setup()
# Import the Student model
from first_app.models import Student
def main():
# Fetch all students from the database
all_students = Student.objects.all()
# Check if there are students
if all_students.exists():
# Get the second student
second_student = all_students[1]
# Delete the second student permanently
second_student.delete()
print("Second student deleted successfully.")
else:
print("No students found in the database.")
# Call the main function
if __name__ == "__main__":
main()
delete_students.py

After creating the required files, now it’s time to compile them.

Execute the example

A Django application to demonstrate hard delete

Now, if we want to execute the above Python scripts, execute the following commands.

cd /usercode/first_project && python3 manage.py makemigrations && python3 manage.py migrate
python3 create_students.py
python3 delete_students.py
Commands to create and delete students

After execution of create_students.py, it will create three students into the database, while after execution of the delete_students.py , the second Student from the database will be deleted.

Note: Make sure to execute the above commands after pressing the Run button, every time you update the code and want to re-run it.

Delete by filter

We can also delete objects in bulk. Every QuerySetIt is a collection of database queries that can be filtered, sliced, and manipulated to retrieve data from the database. has a delete() method which deletes all members of that QuerySet.

For example, the following code will delete all Student objects with a degree of “CS”.

# delete_students.py
import os
import sys
import django
# Set up Django environment
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'first_project.settings.py')
django.setup()
# Import the Student model
from first_app.models import Student
def main():
# Fetch all students from the database
all_students = Student.objects.all()
# Filter students with 'CS' degree and delete them
deleted_students_count, deleted_students_info = all_students.filter(degree='CS').delete()
#output will be look like this
#(2, {'first_app.Student': 2})
#The first value 2 indicates that 2 students were deleted, and the dictionary {first_app.Student: 2}
#specifies that both deletions belonged to the Student model in the first_app application.
print(f"Deleted {deleted_students_count} students.")
print(f"Deletions info: {deleted_students_info}")
# Call the main function
if __name__ == "__main__":
main()
delete_students.py for deletion by filter

In filter function multiple filters can be added. For example, if we want to delete entries based on a partial match of the roll number where it starts with “CS,” we can use the startswith lookup in Django.

all_students.filter(roll_no__startswith='CS').delete()
Delete students using a filter in delete_students.py
A Django application to demonstrate delete by filter

Use the following terminal commands to view the demonstration of filtering deleted records:

cd /usercode/first_project && python3 manage.py makemigrations && python3 manage.py migrate
python3 create_students.py
python3 delete_students.py
Commands to create and delete students

Cascading delete

When Django performs the deletion of an object, it typically follows the behavior of the SQL constraint ON_DELETE=CASCADE. This means any objects with foreign keys pointing at the deleted object will also be deleted. To understand it, let’s add another model name as Enrollment in the models.py file after the Student model.

class Enrollment(models.Model):
student = models.ForeignKey(Student, on_delete=models.CASCADE)
course = models.CharField(max_length=100)
Enrollement class in models.py

Now, if we have two Student objects with a ‘CS’ degree and they are enrolled in some courses, and we execute delete_students.py. The Enrollment model has a foreign critical relationship with the Student model and on_delete=models.CASCADE option is set, then when we delete the Student with a ‘CS’ degree, or any related Enrollment will also be deleted automatically.

all_students.filter(degree = 'CS').delete()
# output will be look like this
# Deleted 5 items.
# Deletions info: {'first_app.Enrollment': 3, 'first_app.Student': 2}
#This indicates that 2 students and their corresponding 3 enrollments were deleted during the operation.
Delete student by specifying degree in delete_students.py

Here is a Django application that combines all of the above code snippets together.

A Django application to demonstrate cascading delete

Use the following terminal commands to view the demonstration of cascading deleted records:

cd /usercode/first_project && python3 manage.py makemigrations && python3 manage.py migrate
python3 create_students.py
python3 delete_students.py
Commands to create and delete students

Soft delete 

Soft deletion is the process of eliminating records in a way that keeps them in the database while making them unavailable to the user. This is done using a flag to mark the record as unavailable rather than completely deleting it from the database.

Pros of soft delete

The main benefit of soft delete is that it lets you get back data that was deleted by mistake. It also puts less pressure on the server because the data isn't really removed, just marked as deleted by changing a field.

Cons of soft delete

It may increase the database size as time passes, potentially causing performance problems as it expands. It also added the complexity of sorting out records marked as deleted.

Implementation of soft delete

We need to create BaseModel class, a custom model class that serves as a base or abstract class for other models in our application. It is common practice in Django to create a base model with commonly used fields or methods and then have other models inherited from this base model in our application.

#models.py
from django.db import models
class BaseModel(models.Model):
   class Meta:
abstract = True
   # common fields go here
BaseModel class in models.py

Add the delete flag in our BaseModel class. The is_deleted field will inform us about the availability of the record.

is_deleted = models.BooleanField(default=False)
is_deleted flag incorporated in BaseModel

Also, we customize the model’s delete method, allowing us to modify the default behavior of our model's deletion process from permanent to soft.

#models.py
from django.db import models
class BaseModel(models.Model):
   class Meta:
abstract = True
   # common fields go here
is_deleted = models.BooleanField(default=False)
def delete(self):
"""Mark the record as deleted instead of deleting it"""
self.is_deleted = True
self.save()
BaseModel class in models.py

Now, make a slight change to the Student model class.

from django.db import models
#previously it was:
#class Student(models.Model):
#now we use our customized model class
class Student(BaseModel):
#all other code is same as previous
Student class in models.py

Now, if we execute create_students.py and delete_students.py, it will mark the second Student object deleted instead of deleting the record from the database.

For the given query Student.objects.all(), it is imperative to guarantee that the query results consistently exclude deleted records. This is achieved by implementing a custom manager to filter out the deleted records. Add the BaseModelManager and update BaseModel codes in models.py the file.

class BaseModelManager(models.Manager):
def get_queryset(self):
return super().get_queryset().filter(deleted=False)
class BaseModel(model.Model):
class Meta:
abstract = True
   # common fields go here
is_deleted = models.BooleanField(default=False)
def delete(self):
"""Mark the record as deleted instead of deleting it"""
self.is_deleted = True
self.save()
#if we fetch objects, then custom manager will called
objects = AppManager()
models.py

Finally, we have implemented soft delete.

# fetch all student from database where is_deleted == false
all_students = Student.objects.all()
fetch all students where is_delete is false

A Django application to demonstrate soft delete

Use the following terminal commands to view the demonstration of soft deleted records:

cd /usercode/first_project && python3 manage.py makemigrations && python3 manage.py migrate
python3 create_students.py
python3 delete_students.py
Commands to create and delete students

Wrap up

When removing objects, the choice between hard delete and soft delete depends entirely on the specific scenario. No universal rule favors soft delete over hard delete or vice versa. The effectiveness of each method is contingent on the nature of the project.

Free Resources

Copyright ©2025 Educative, Inc. All rights reserved