https://github.com/parcellab/django-mongo-backend
MongoDB database adapter & compiler for Django
https://github.com/parcellab/django-mongo-backend
django open-source team-backend
Last synced: 12 months ago
JSON representation
MongoDB database adapter & compiler for Django
- Host: GitHub
- URL: https://github.com/parcellab/django-mongo-backend
- Owner: parcelLab
- Created: 2024-01-19T10:43:52.000Z (about 2 years ago)
- Default Branch: main
- Last Pushed: 2025-02-12T07:59:10.000Z (about 1 year ago)
- Last Synced: 2025-02-12T08:51:39.553Z (about 1 year ago)
- Topics: django, open-source, team-backend
- Language: Python
- Size: 95.7 KB
- Stars: 0
- Watchers: 10
- Forks: 0
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
## Django backend for MongoDB
Django backend for MongoDB.
Supports:
- Column mappings to MongoDB documents
- Single table (collection) inheritance and single table OneToOne relationships
- Filters (filter/exclude)
## Setup / Configuration
Not supported as primary database, as Django contrib apps rely on Integer primary keys in built in migrations (and
because it is a use case that is not a priority at the moment).
```python
# settings.py
DATABASES = {
# or any other primary databse
"default": {
"ENGINE": "django.db.backends.sqlite3",
"NAME": BASE_DIR / "db.sqlite3",
},
# mongodb database, Client constructor options are passe in 'CLIENT', the database name in 'NAME'
"mongodb": {
"ENGINE": "django_mongodb",
"NAME": "django_mongodb",
"CONN_MAX_AGE": 120,
"CLIENT": {
"host": os.environ.get("MONGODB_URL"),
},
},
}
# A database is required
DATABASE_ROUTERS = ["testproject.router.DatabaseRouter"]
```
Using the database in models requires a DatabaseRouter, which could look like this
```python
class DatabaseRouter:
def db_for_read(self, model, **hints):
if model._meta.app_label == "mymongoapp":
return "default"
return "default"
def db_for_write(self, model, **hints):
if model._meta.app_label == "mymongoapp":
return "default"
return "default"
def allow_relation(self, obj1, obj2, **hints):
if obj1._meta.app_label == obj2._meta.app_label:
return True
return None
def allow_migrate(self, db, app_label, model_name=None, **hints):
if app_label == "mymongoapp":
# we are disabling migrations, as MongoDB is schema-less. Alerts, such as renaming fields, etc. are not supported
return False
return None
```
Finally we are going to change the default primary key of the app using MongoDB (if that is the case, otherwise add
ObjectIdAutoField to the models, where you need it).
```python
# apps.py
class TestappConfig(AppConfig):
default_auto_field = "django_mongodb.models.ObjectIdAutoField"
name = "mymongoapp"
```
### Defining Models
A simple model, in an app, which has `ObjectIdAutoField` as `default_auto_field`
```python
class MyModel(models.Model):
json_field = JSONField()
name = models.CharField(max_length=100)
datetime_field = models.DateTimeField(auto_now_add=True)
time_field = models.TimeField(auto_now_add=True)
date_field = models.DateField(auto_now_add=True)
```
Single table inheritance
```python
class SameTableChild(MyModel):
my_model_ptr = models.OneToOneField(
MyModel,
on_delete=models.CASCADE,
parent_link=True,
related_name="same_table_child",
# pointer to the primary key of the parent model
db_column="_id",
)
extended = models.CharField(max_length=100)
class Meta:
# We are using the parent collection as db_table
db_table = "mymongoapp_mymodel"
```
Single table `OneToOne` relationships
```python
class SameTableOneToOne(models.Model):
dummy_model = models.OneToOneField(
MyModel,
primary_key=True,
on_delete=models.CASCADE,
related_name="extends",
db_column="_id",
)
extra = models.CharField(max_length=100)
class Meta:
# we are using the same collection to persist one-to-one relationships
db_table = "mymongoapp_mymodel"
```
### Querying
```python
# get all objects
MyModel.objects.all()
# get all objects, which have a name in list ["foo", "bar"]
MyModel.objects.filter(name_in=["foo", "bar"])
# select related with single table inheritance and one to one relationships
MyModel.objects.select_related("same_table_child", "extends").all()
# simple aggregations
MyModel.objects.filter(name_in=["foo", "bar"]).count()
# raw mongo filter
MyModel.objects.filter(RawMongoDBQuery({"name": "1"})).delete()
```
### Search
Using the `prefer_search()` extension of MongoQueryset, we can use the `$search` operator of MongoDB to query,
if we have search indexes configured on the model.
```python
MyModel.objects.prefer_search().filter(name="foo").all()
```
PostgreSQL search vectors map down to MongoDB search indexes, so we can use the same syntax as with PostgreSQL.
```python
class MyModel(models.Model):
name = models.CharField(max_length=100)
```
```python
MyModel.objects.annotate(search=SearchVector('name')).filter(search=SearchQuery('foo')).all()
```
### Raw Queries
```python
with connections["mongodb"].cursor() as cursor:
doc = cursor.collections["my_collection"].find_one()
assert isinstance(doc["_id"], ObjectId)
```