django-couchbase-orm
Live Demo: brewsync.simonian.online · iOS app A full Django + Wagtail CMS + DRF beer catalog running on Couchbase Capella. Browse beers, read the blog, or explore the Wagtail admin.
Use Couchbase as your Django database. Drop-in backend for django.db.models.Model plus a standalone Document API for Couchbase-native patterns.
Docs: Database Backend | Document API | Wagtail | Hybrid Architecture | Testing
Two Ways to Use It
1. Django Database Backend
Standard Django models work transparently with Couchbase. Admin, forms, DRF, Wagtail - everything just works.
# settings.py
DATABASES = {
"default": {
"ENGINE": "django_couchbase_orm.db.backends.couchbase",
"NAME": "mybucket",
"USER": "Administrator",
"PASSWORD": "password",
"HOST": "couchbase://localhost",
}
}
DEFAULT_AUTO_FIELD = "django_couchbase_orm.db.backends.couchbase.fields.CouchbaseAutoField"
# models.py - standard Django models, no changes needed
from django.db import models
class Article(models.Model):
title = models.CharField(max_length=200)
body = models.TextField()
author = models.ForeignKey("auth.User", on_delete=models.CASCADE)
published = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
Everything works: makemigrations, migrate, createsuperuser, Django admin, ModelForms, DRF serializers, Wagtail CMS.
2. Document API
For Couchbase-native patterns - subdoc operations, KV fast-path, embedded documents.
# settings.py
COUCHBASE = {
"default": {
"CONNECTION_STRING": "couchbase://localhost",
"USERNAME": "Administrator",
"PASSWORD": "password",
"BUCKET": "mybucket",
}
}
# documents.py
from django_couchbase_orm import Document, StringField, FloatField
class Beer(Document):
name = StringField(required=True)
abv = FloatField()
style = StringField()
class Meta:
collection_name = "beers"
Both APIs can coexist in the same project. They share the same Couchbase connection.
Install
pip install django-couchbase-orm
Requires Python 3.10+, Django 4.2+, Couchbase SDK 4.1+.
Django Backend Features
Everything you'd expect from a Django database backend:
manage.py migratecreates Couchbase collectionsmanage.py createsuperuserworksForeignKey,ManyToManyFieldwith JOINs via N1QLselect_related(),prefetch_related()annotate(),aggregate()withCount,Sum,Avg,Min,MaxQ()objects,F()expressions- All lookups:
exact,icontains,startswith,in,isnull,regex, etc. values(),values_list(),distinct(),only(),defer()bulk_create(),bulk_update()- Django admin: list, add, edit, delete, search
- Django auth: users, groups, permissions
- Django sessions (DB backend)
- ContentTypes framework
- ModelForm, DRF ModelSerializer
- Wagtail CMS (page tree, publishing, admin)
SQL-to-N1QL Translation
The backend transparently handles the differences between SQL and N1QL:
| SQL | N1QL (handled automatically) |
|---|---|
INSERT INTO |
INSERT INTO (raises IntegrityError on duplicate PK; use update_conflicts=True for upsert) |
SUBSTRING(s, pos) |
SUBSTR(s, pos-1) (0-indexed) |
IS NULL |
IS NOT VALUED (handles MISSING) |
CAST(x AS INT) |
TONUMBER(x) |
AUTO_INCREMENT |
Atomic counter (binary.increment) |
| Sequential IDs | CouchbaseAutoField (integer PKs) |
Wagtail Support
Wagtail CMS works fully with the Couchbase backend. See the live demo for a working example.
INSTALLED_APPS = [
...
"wagtail", "wagtail.admin", "wagtail.images",
"wagtail.documents", "wagtail.search",
]
# manage.py migrate - creates all Wagtail collections
# manage.py createsuperuser - create admin user
# Page tree, publishing, editing, images, documents all work
Couchbase Capella (Cloud)
Works with Couchbase Capella out of the box:
DATABASES = {
"default": {
"ENGINE": "django_couchbase_orm.db.backends.couchbase",
"NAME": "my-bucket",
"USER": "dbuser",
"PASSWORD": "dbpassword",
"HOST": "couchbases://cb.xxxxx.cloud.couchbase.com",
}
}
Document API Features
For when you need Couchbase-native performance:
- KV-optimized
get(pk=...)(~1ms vs ~50ms for N1QL) - Sub-document operations (partial reads/writes)
- Embedded documents
- Django-style QuerySet with N1QL
- Signals:
pre_save,post_save,pre_delete,post_delete - Async support (
asave,adelete,alist,acount) - Custom migrations framework (
cb_makemigrations,cb_migrate)
Quick Example
from django_couchbase_orm import Document, StringField, FloatField, Q
# CRUD
beer = Beer(name="IPA", abv=6.5, style="IPA")
beer.save()
beer = Beer.objects.get(pk="beer-id") # fast KV lookup
beer.abv = 7.0
beer.save()
beer.delete()
# Queries
Beer.objects.filter(style="IPA", abv__gte=6.0).order_by("-abv")[:20]
Beer.objects.filter(Q(style="IPA") | Q(style="Pale Ale")).count()
Beer.objects.aggregate(avg_abv=Avg("abv"), total=Count("*"))
# Sub-document operations
beer.subdoc.upsert("ratings.average", 4.5)
beer.subdoc.increment("view_count", 1)
beer.subdoc.array_append("tags", "hoppy")
Configuration
Database Backend (recommended)
DATABASES = {
"default": {
"ENGINE": "django_couchbase_orm.db.backends.couchbase",
"NAME": "mybucket", # Couchbase bucket
"USER": "Administrator",
"PASSWORD": "password",
"HOST": "couchbase://localhost",
"OPTIONS": {
"SCOPE": "_default", # optional
},
}
}
DEFAULT_AUTO_FIELD = "django_couchbase_orm.db.backends.couchbase.fields.CouchbaseAutoField"
Document API
COUCHBASE = {
"default": {
"CONNECTION_STRING": "couchbase://localhost",
"USERNAME": "Administrator",
"PASSWORD": "password",
"BUCKET": "mybucket",
"SCOPE": "_default",
}
}
If you use the database backend, the Document API auto-derives its config from DATABASES - no need to set both.
Fields (Document API)
| Field | Type | Options |
|---|---|---|
StringField |
str |
min_length, max_length, regex |
IntegerField |
int |
min_value, max_value |
FloatField |
float |
min_value, max_value |
BooleanField |
bool |
|
UUIDField |
uuid.UUID |
auto=True |
DateTimeField |
datetime |
auto_now, auto_now_add |
DateField |
date |
auto_now, auto_now_add |
ListField |
list |
field for typed elements |
DictField |
dict |
|
EmbeddedDocumentField |
nested | |
ReferenceField |
FK-like |
Known Limitations
- Transactions:
atomic()issues N1QLBEGIN WORK/COMMIT WORK/ROLLBACK WORK. The defaultDURABILITY_LEVEL='none'works on both single-node and multi-node clusters; raising durability above'none'requires replica nodes. IfBEGIN WORKfails the call now raisesOperationalErrorrather than silently autocommitting — setOPTIONS['TRANSACTIONS']='disabled'onDATABASESto opt out and makeatomic()a true no-op. - INSERT semantics:
Model.objects.create(...)andbulk_create(...)now useINSERT INTOand raiseIntegrityErroron a duplicate PK instead of silently overwriting. Usebulk_create(objs, update_conflicts=True)for upsert behavior. - Document API CAS:
Document.save()does an optimistic-lockreplacewith the CAS captured at load time and raisesConcurrentModificationErroron conflict. Passsave(cas=False)for last-writer-wins. - Query errors: N1QL syntax/unsupported-pattern errors now propagate by default. Set
OPTIONS['GRACEFUL_QUERY_ERRORS']=Trueif you want the prior fail-soft behavior for SELECT (returns empty results, logs the error). - Window functions / UNION / partial / expression indexes: not advertised as supported. Re-enable individually only after backend integration coverage is added.
- Page moves: Wagtail page tree moves use raw SQL with reserved words. Use delete + recreate as a workaround.
- Multi-table inheritance: Works but may have performance implications with N1QL JOINs.
Tests
1,275 tests across 48 test modules, tested on Python 3.10 - 3.14. All tests run against a real Dockerized Couchbase instance — no mocks for query execution.
| Suite | Tests | What's Covered |
|---|---|---|
| Document API | 784 | Fields, QuerySet, Manager, Document CRUD, signals, pagination, migrations, auth, sessions |
| Django Backend | 156 | Connection, cursor, CRUD, JOINs, M2M, admin, forms, migrations, subqueries, bulk ops |
| Edge Cases | 128 | Boundary conditions, type coercion, null handling, return types, regression tests |
| Coverage Gaps | 114 | N1QL builders, paginator, signals, document options, aggregate+filter combos |
| Wagtail CRUD | 28 | Page create, publish, edit, unpublish, delete, revisions, admin forms |
| Security | 27 | Injection prevention, password isolation, backtick escaping |
| Concurrency | 18 | Multi-threaded CRUD, connection pool thread safety, race conditions, auto-increment contention |
# Start Couchbase
docker compose -f docker-compose.test.yml up -d
./scripts/setup-test-couchbase.sh
# Run all tests
CB_BUCKET=testbucket pytest tests/ --ignore=tests/testapp --ignore=tests/wagtailapp
# Coverage
CB_BUCKET=testbucket coverage run -m pytest tests/ && coverage report --include="src/*"
See Testing Guide for full details.
Example Project
The example/ directory contains a complete Django + Wagtail + DRF project (BrewSync) deployed at the live demo. It includes:
- Wagtail CMS with HomePage, BlogIndexPage, BlogPage
- Beer catalog with Brewery/Beer models
- DRF REST API (
/api/beers/,/api/breweries/) - Dark brewery theme with search and filtering
- Deployed on Railway with Couchbase Capella
Development
git clone https://github.com/EdikSimonian/django-couchbase-orm.git
cd django-couchbase-orm
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
pytest
Changelog
See CHANGELOG.md for release history and migration notes.
License
Apache 2.0
Metadata
Release files for django-couchbase-orm 1.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| django_couchbase_orm-1.3.0.tar.gz | 311.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| django_couchbase_orm-1.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 416.4 kB
Release files / django_couchbase_orm-1.3.0.tar.gz
| Download URL | django_couchbase_orm-1.3.0.tar.gz |
|---|---|
| Size | 311.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
07311b8e040eff5378fa5dd06142f1b0285c5431cf37dbd6dbb9a807b024cb30
|
|
BLAKE2b-256 checksum How to use checksums |
b585d14cea5d61d09648a0610ce3d2778855e14023e9a9de8638240cb96e39a8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 2, 2026.
Transparency logRelease files / django_couchbase_orm-1.3.0-py3-none-any.whl
| Download URL | django_couchbase_orm-1.3.0-py3-none-any.whl |
|---|---|
| Size | 105.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
fdb57427a462c4d9904b6636df18664de26e54bf5e04ad610b97ac5f8fae1e7a
|
|
BLAKE2b-256 checksum How to use checksums |
6fc238a828375fcf562c45ced5f83de99284d97e4aac10da847bd0bb0bb1d473
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 2, 2026.
Transparency log