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
muslpy 3.10–3.95 runs
installs and imports cleanly · install 0.0s · import 0.740s · 66.4MB
glibcpy 3.10–3.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))
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.
fixEnsure 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.
fixReview 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.
fixFirst, 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.
fixEnsure 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).