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 anis_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 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.
It’s easy to implement. There is no need to keep track of deleted records. It may reduce the database size.
Retrieving deleted data becomes impossible. Executing a delete()
command for hard deletion tends to be slower, especially with interconnected records across tables.
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_projectcd first_project && python3 manage.py startapp 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 definitionINSTALLED_APPS = [#existing apps'first_app']
Now, define a Student
model in the models.py
file of our application.
#models.pyfrom django.db import modelsclass 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)
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 makemigrationspython3 manage.py migrate
We create a file like create_students.py
to show how to store some Student
objects in the database.
# create_students.pyimport osimport sysimport django# Set up Django environmentos.environ.setdefault('DJANGO_SETTINGS_MODULE', 'first_project.settings')django.setup()# Import the Student modelfrom first_app.models import Studentdef main():# Create Student objects and set their attributesstudent1 = 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 databasestudent1.save()student2.save()student3.save()print("Students created successfully.")# Call the main functionif __name__ == "__main__":main()
We create a file like delete_students.py
to show how to delete the second Student
object in the database.
# delete_students.pyimport osimport sysimport django# Set up Django environmentos.environ.setdefault('DJANGO_SETTINGS_MODULE', 'first_project.settings')django.setup()# Import the Student modelfrom first_app.models import Studentdef main():# Fetch all students from the databaseall_students = Student.objects.all()# Check if there are studentsif all_students.exists():# Get the second studentsecond_student = all_students[1]# Delete the second student permanentlysecond_student.delete()print("Second student deleted successfully.")else:print("No students found in the database.")# Call the main functionif __name__ == "__main__":main()
After creating the required files, now it’s time to compile them.
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 migratepython3 create_students.pypython3 delete_students.py
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.
We can also delete objects in bulk. Every 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.pyimport osimport sysimport django# Set up Django environmentos.environ.setdefault('DJANGO_SETTINGS_MODULE', 'first_project.settings.py')django.setup()# Import the Student modelfrom first_app.models import Studentdef main():# Fetch all students from the databaseall_students = Student.objects.all()# Filter students with 'CS' degree and delete themdeleted_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 functionif __name__ == "__main__":main()
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()
Use the following terminal commands to view the demonstration of filtering deleted records:
cd /usercode/first_project && python3 manage.py makemigrations && python3 manage.py migratepython3 create_students.pypython3 delete_students.py
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)
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.
Here is a Django application that combines all of the above code snippets together.
Use the following terminal commands to view the demonstration of cascading deleted records:
cd /usercode/first_project && python3 manage.py makemigrations && python3 manage.py migratepython3 create_students.pypython3 delete_students.py
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.
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.
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.
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.pyfrom django.db import modelsclass BaseModel(models.Model):class Meta:abstract = True# common fields go here
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)
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.pyfrom django.db import modelsclass BaseModel(models.Model):class Meta:abstract = True# common fields go hereis_deleted = models.BooleanField(default=False)def delete(self):"""Mark the record as deleted instead of deleting it"""self.is_deleted = Trueself.save()
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 classclass Student(BaseModel):#all other code is same as previous
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 hereis_deleted = models.BooleanField(default=False)def delete(self):"""Mark the record as deleted instead of deleting it"""self.is_deleted = Trueself.save()#if we fetch objects, then custom manager will calledobjects = AppManager()
Finally, we have implemented soft delete.
# fetch all student from database where is_deleted == falseall_students = Student.objects.all()
Use the following terminal commands to view the demonstration of soft deleted records:
cd /usercode/first_project && python3 manage.py makemigrations && python3 manage.py migratepython3 create_students.pypython3 delete_students.py
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