Execute Native SQL in Django and Return Results as Dictionaries

This article explains three ways to run raw SQL in Django, demonstrates why the built‑in extra method is discouraged, shows how to use the raw manager and the low‑level connection cursor, and provides helper functions that return query results as dictionaries for easier processing.

Python Crawling & Data Mining
Python Crawling & Data Mining
Python Crawling & Data Mining
Execute Native SQL in Django and Return Results as Dictionaries

Preface

In this tutorial we explore how to execute native SQL statements within a Django project.

Why Use Native SQL?

Django's ORM covers most use‑cases, but for the remaining 20% you may need direct SQL.

Table Structure

Example model:

class Book(models.Model):
    title = models.CharField(verbose_name="书名", max_length=32)
    describe = models.TextField(verbose_name="描述")
    author = models.CharField(verbose_name="作者", max_length=32)
    publisher = models.CharField(verbose_name="出版社", max_length=32)
    publisher_date = models.DateField(verbose_name="publisher")

The table can be populated via the Django admin.

extra Method

The extra method is deprecated and not recommended.

raw Method

The raw manager allows simple raw queries:

ModelName.objects.raw(sql)
ModelName.objects.raw(sql, [param1, param2])

It returns model instances.

True Native SQL with Connection

For completely unbound SQL, import the low‑level connection:

from django.db import connection

def book_list(request):
    cursor = connection.cursor()
    cursor.execute("select * from app01_book where id=%s", [1])
    rows = cursor.fetchall()
    print(rows)

This returns a list of tuples.

Helper Functions Returning Dictionaries

Two utility functions wrap the cursor logic and convert results to dictionaries.

def query_all_dict(sql, params=None):
    """Return all rows as a list of dicts."""
    with connection.cursor() as cursor:
        if params:
            cursor.execute(sql, params=params)
        else:
            cursor.execute(sql)
        col_names = [desc[0] for desc in cursor.description]
        rows = cursor.fetchall()
        return [dict(zip(col_names, row)) for row in rows]

def query_one_dict(sql, params=None):
    """Return a single row as a dict."""
    with connection.cursor() as cursor:
        if params:
            cursor.execute(sql, params=params)
        else:
            cursor.execute(sql)
        col_names = [desc[0] for desc in cursor.description]
        row = cursor.fetchone()
        return dict(zip(col_names, row))

Use these functions directly in views to obtain results as [{...}, {...}] structures.

Summary

Django offers three ways to run raw SQL: extra (generally useless), raw (works but still tied to the model), and the low‑level connection cursor (most flexible). The helper functions query_all_dict and query_one_dict simplify retrieving results as dictionaries.

Recommendation

Prefer the query_all_dict and query_one_dict utilities for clean, dictionary‑based results.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

PythonSQLdatabaseDjangoRaw Query
Python Crawling & Data Mining
Written by

Python Crawling & Data Mining

Life's short, I code in Python. This channel shares Python web crawling, data mining, analysis, processing, visualization, automated testing, DevOps, big data, AI, cloud computing, machine learning tools, resources, news, technical articles, tutorial videos and learning materials. Join us!

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.