Registry / database / django-cte

django-cte

JSON →
library3.0.0pypypi✓ verified 23d ago

django-cte provides a seamless way to integrate Common Table Expressions (CTEs) into Django's ORM, allowing developers to write complex, hierarchical, and recursive SQL queries more readably and efficiently directly within their Django applications. It is currently at version 3.0.0 and is actively maintained, with releases primarily driven by new features or compatibility requirements with Django versions.

pip install django-cte
INSTALL
IMPORT
SIG · DJANGO-CTE
D
django-cte
databasepythonv3.0.0
Install
3.5s avg
Import
706ms
Disk
66MB
Pass rate
10/ 10
Env Coverage10 / 10
glibc
3.93.13
musl
3.93.13
Install & Compatibility
Where this runs
tested against v3.0.0 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
musl
py 3.103.95 runs
installs and imports cleanly · install 0.0s · import 0.740s · 66.4MB
glibc
py 3.103.95 runs
installs and imports cleanly · install 3.5s · import 0.672s · 67MB
66MB installed
● package 66MB
Code
Verified usage

Verified import paths — ran on the pinned version, not inferred.

CTE
from django_cte import CTE
with_cte
from django_cte import with_cte
With
from django_cte import With
Used for defining recursive CTEs.
CustomModelManager
class MyModelManager(CTEManager): pass class MyModel(models.Model): objects = MyModelManager()
Prior to v2.0, a custom model manager (e.g., inheriting from CTEManager or similar) was often required. This is no longer necessary in v2.0 and later.

This quickstart demonstrates how to define a simple CTE to calculate aggregated values (sum of amounts per region) and then join it back to the original `Order` model to annotate each order with its region's total. For recursive CTEs, the `With` class is used, followed by a `.recursive()` call.

import os from django.db import models from django.db.models import Sum from django_cte import CTE, with_cte # Assume a Django setup and an 'orders' app # For runnable example, we define a minimal model class Order(models.Model): region_id = models.IntegerField() amount = models.DecimalField(max_digits=10, decimal_places=2) class Meta: app_label = 'orders' # Minimal Django settings for ORM to function # In a real project, this would be in settings.py if not os.environ.get('DJANGO_SETTINGS_MODULE'): os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings') try: import django django.setup() except ImportError: print("Django is not set up. This example requires a minimal Django environment.") # Example: Calculate total amount per region using a CTE # and then join it back to annotate individual orders. # 1. Define the CTE cte_region_totals = CTE( Order.objects .values("region_id") .annotate(total_amount=Sum("amount")) .order_by() ) # 2. Use with_cte to apply the CTE and join it to the main query orders_with_region_totals = with_cte( cte_region_totals, select=cte_region_totals.join(Order, region_id=cte_region_totals.col.region_id) .annotate(region_total_sum=cte_region_totals.col.total_amount) ) # This would typically be executed in a view or script # For demonstration, we'll print the query. # In a real application, you would iterate orders_with_region_totals # For example: # for order in orders_with_region_totals.all(): # print(f"Order {order.id} in region {order.region_id} has total for region: {order.region_total_sum}") print("Example CTE query (SQL):") print(str(orders_with_region_totals.all().query)) # Example for recursive CTE (conceptual, requires more setup) # from django_cte import With # with_employees = With( # Employee.objects.filter(manager__isnull=True).values('id', 'name', 'manager_id', 'depth', models.Value(0, output_field=models.IntegerField())), # name='ancestors' # ) # recursive_cte = with_employees.recursive( # Employee.objects.filter(manager=with_employees.col.id) # .values('id', 'name', 'manager_id', 'depth', with_employees.col.depth + 1) # ) # employees_hierarchy = with_cte(recursive_cte, select=recursive_cte.join(Employee, id=recursive_cte.col.id)) # print(str(employees_hierarchy.all().query))
Debug
Known issues
breakingThe API for defining CTEs changed significantly in `django-cte` v2.0. The requirement for a custom model manager on your models for CTE queries was removed.
fix
Update your code to use the `CTE(...)` and `with_cte(...)` functions directly on standard Django QuerySets. Custom model managers are no longer needed.
affects: <2.0.0
gotchaWhile `django-cte` brings CTEs to Django's ORM, it's an abstraction. Developers should still have a foundational understanding of SQL CTEs to effectively use the library, especially for complex or recursive queries. The `with_cte` function modifies querysets in specific ways that might differ from native ORM chaining.
fix
Familiarize yourself with SQL Common Table Expressions and review the `django-cte` documentation for patterns on simple, named, recursive, and materialized CTEs to ensure correct ORM integration.
affects: All
gotchaThe `materialized=True` option for CTEs is a database-specific feature. It is only supported by PostgreSQL 12+ and SQLite 3.35+.
fix
Ensure your database server meets the minimum version requirements if you intend to use materialized CTEs. Otherwise, omit the `materialized=True` parameter.
affects: All
Errors
Common errors & fixes
AttributeError: 'QuerySet' object has no attribute 'with_cte'
This error occurs because `with_cte` is a method provided by `django-cte`'s `CTEManager` or `CTEQuerySet`, and it is being called on a standard Django `QuerySet` which does not have this method.
fix
Ensure your model's manager inherits from `django_cte.CTEManager` or your custom `QuerySet` inherits from `django_cte.CTEQuerySet`. For example: `from django_cte import CTEManager; class MyModel(models.Model): objects = CTEManager()`.
django.db.utils.ProgrammingError: recursive query "cte" does not have the form non-recursive-term UNION [ALL] recursive-term
This error typically arises when defining a recursive CTE with `django-cte` where the recursive part of the `UNION` operation is incorrectly structured, or Django's ORM implicitly optimizes away a part of the query that is essential for a valid recursive CTE.
fix
Review the `CTE.recursive()` definition to ensure both the non-recursive (base) and recursive terms are correctly formed and explicitly joined with `union(..., all=True)`. Sometimes, ensuring a base case exists that will always return rows can prevent Django from optimizing away the union.
ModuleNotFoundError: No module named 'django_cte'
This error means the `django-cte` package is either not installed, or it has not been added to your Django project's `INSTALLED_APPS` setting, or there is a typo in the import statement.
fix
First, install the package using `pip install django-cte`. Then, add `'django_cte'` to your `INSTALLED_APPS` list in your Django project's `settings.py` file..
ValueError: This queryset contains a reference to an outer query and may only be used in a subquery.
This error occurs when an `OuterRef` is used within a `With` object in `django-cte` in a way that the ORM cannot correctly resolve the outer reference, indicating an invalid nesting or usage pattern for correlated subqueries within CTEs.
fix
Ensure that `OuterRef` is used correctly to link the CTE to the outer query. This error often points to a logical issue in how the inner (CTE) queryset is attempting to reference fields from the outer queryset. Re-evaluate the query structure and the placement of `OuterRef` to ensure it's within a context where Django can interpret it as a subquery correlation.
Upgrade
Version history
3.0.0latest on PyPI · released Feb 5, 2026
Audit
Dependencies
DjangorequiredCore functionality as an ORM extension for Django. Requires a compatible Django version (not strictly version-locked in PyPI, but functional dependency).
Agent activity
9 hits · last 30 days
node
8
Resources
django-cte — pip install django-cte · libregistry