Harnessing Raw SQL Power: Creating Custom Views with Django Migrations

Creating a View on Database by Using Django Migrations

4 min readFeb 16, 2024


Django migrations are more than just tools for managing your database schema changes. They offer a robust framework for keeping track of your evolving data model and applying those changes in a controlled and reliable manner. While the Django ORM excels in handling most data interactions, there are situations where venturing into the realm of raw SQL becomes necessary. This article explores how to harness the power of raw SQL within Django migrations and demonstrates its application in creating a custom view — a powerful mechanism for retrieving and presenting your data efficiently.

Photo by Brecht Corbeel on Unsplash

When Does Raw SQL Step In?

While the Django ORM is your go-to companion for interacting with your database, it’s not a one-size-fits-all solution. Complex scenarios sometimes demand the full expressiveness and fine-grained control offered by raw SQL. Here are some instances where you might consider it:

  • Uncharted Territory: Tasks like creating views, stored procedures, or triggers might not have corresponding methods in the ORM.
  • Performance Optimization: For intricate queries involving specialized functions or non-standard joins, raw SQL can provide a significant performance boost.
  • Database-Specific Gems: Unleashing the power of features unique to your specific database requires venturing beyond the ORM’s boundaries.

Case Study: Building a User Activity Powerhouse

Imagine developing a data platform where users perform diverse actions like generating reports, downloading datasets, and managing workspaces. To gain insightful understanding of user activity across these functionalities, you require a consolidated view that merges data from multiple tables.

Django migrations empower you to construct such a view using raw SQL. Let’s delve into the key aspects:

  • The RunSQL Operation: This workhorse within migrations allows executing arbitrary SQL statements directly within the migration file.
  • Crafting the View: Your custom SQL query defines the view, carefully selecting relevant fields from various tables. It acts as a blueprint for how data will be retrieved and presented.
  • Joins: The Connectors: The query leverages LEFT JOINs to establish connections between tables based on foreign key relationships, ensuring all essential information is incorporated into the view.
  • Data Extraction and Formatting: The query extracts the desired data, often employing functions to process it into a user-friendly format. String manipulation might be used to remove unnecessary characters or adjust casing for consistency.

Advantages and Cautions: Wielding Power Responsibly

Employing raw SQL in migrations grants you flexibility and control over your database interactions. However, it’s crucial to wield this power judiciously:

  • Clarity is Key: Ensure thorough documentation and comments within the migration file, explaining the purpose and logic behind the raw SQL.
  • Testing: Your Safety Net: Write comprehensive tests to verify the view’s functionality and data integrity after applying the migration.
  • Security First: Sanitize any user-provided input within the raw SQL to prevent potential SQL injection vulnerabilities.
  • Version Control: Keeping Track: Treat changes made to the raw SQL with the same importance as your model definitions. Version control ensures easy reference and tracking of modifications.

Beyond the Basics: Exploring Further

This article provides a glimpse into the potential of using raw SQL within Django migrations. Remember, this is just the tip of the iceberg. As you delve deeper, you’ll discover:

  • Advanced Techniques: Explore complex query structures, conditional logic, and stored procedures for even more intricate tasks.
  • Database-Specific Nuances: Learn how to leverage features unique to your chosen database, unlocking its full potential.
  • Community Resources: Tap into the wealth of knowledge and best practices shared by the Django community to guide your explorations.

Dive into a Real-World Example

Let’s take a concrete example to illustrate the power of raw SQL in action. Imagine you’re building a data platform where users perform various actions across reports, datasets, and workspaces. To gain valuable insights into user activity, you need a consolidated view that merges data from multiple tables.

Behold, the vw_user_log View by using the command below.

python manage.py makemigrations --empty my_app

from django.db import migrations

class Migration(migrations.Migration):

dependencies = [
("management", "0094_alter_user_options"),

operations = [
CREATE VIEW vw_user_log as
mul.id as id
,mul.created_at as created_at
,mu.username as username
,me."name" as event_name
--,dct.app_label as app_label
--,dct.model as model_name
,replace(cast(message::json->'data'->'item_name' as varchar),'"','') as item_name
,replace(cast(message::json->'data'->'report_name' as varchar),'"','') as report_name
,replace(cast(message::json->'data'->'rls_profile' as varchar),'"','') as rls_profile
,replace(cast(message::json->'data'->'dataset_name' as varchar),'"','') as dataset_name
,replace(cast(message::json->'data'->'workspace_name' as varchar),'"','') as workspace_name
from management_userlog mul
left join management_user mu on mul.user_id = mu.id
left join management_eventlog me on mul.event_log_id = me.id
left join django_content_type dct on me.content_type_id = dct.id

In Conclusion

While the Django ORM simplifies database interactions, understanding raw SQL empowers you to handle complex scenarios, leverage database-specific functionalities, and tailor data retrieval to your specific needs. Use it judiciously, following best practices for maintainability, security, and testing, to ensure a robust and scalable data management system.

You can find my links below to follow me on other platforms.

Kind regards


You can see my custom user event logging mechanism below.



Writer for

Lifelong learner & Developer. I use technology that helps me. mebaysan.com