Package: django-mongo-backend
Django backend for MongoDBDjango backend for MongoDB.Supports:Column mappings to MongoDB documentsSingle table (collection) inheritance and single table OneToOne relationshipsFilters (filter/exclude)Setup / ConfigurationNot 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).# settings.pyDATABASES={# 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 requiredDATABASE_ROUTERS=["testproject.router.DatabaseRouter"]Using the database in models requires a DatabaseRouter, which could look like thisclassDatabaseRouter:defdb_for_read(self,model,**hints):ifmodel._meta.app_label=="mymongoapp":return"default"return"default"defdb_for_write(self,model,**hints):ifmodel._meta.app_label=="mymongoapp":return"default"return"default"defallow_relation(self,obj1,obj2,**hints):ifobj1._meta.app_label==obj2._meta.app_label:returnTruereturnNonedefallow_migrate(self,db,app_label,model_name=None,**hints):ifapp_label=="mymongoapp":# we are disabling migrations, as MongoDB is schema-less. Alerts, such as renaming fields, etc. are not supportedreturnFalsereturnNoneFinally 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).# apps.pyclassTestappConfig(AppConfig):default_auto_field="django_mongodb.models.ObjectIdAutoField"name="mymongoapp"Defining ModelsA simple model, in an app, which hasObjectIdAutoFieldasdefault_auto_fieldclassMyModel(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 inheritanceclassSameTableChild(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 modeldb_column="_id",)extended=models.CharField(max_length=100)classMeta:# We are using the parent collection as db_tabledb_table="mymongoapp_mymodel"Single tableOneToOnerelationshipsclassSameTableOneToOne(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)classMeta:# we are using the same collection to persist one-to-one relationshipsdb_table="mymongoapp_mymodel"Querying# get all objectsMyModel.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 relationshipsMyModel.objects.select_related("same_table_child","extends").all()# simple aggregationsMyModel.objects.filter(name_in=["foo","bar"]).count()SearchUsing theprefer_search()extension of MongoQueryset, we can use the$searchoperator of MongoDB to query,
if we have search indexes configured on the model.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.classMyModel(models.Model):name=models.CharField(max_length=100)MyModel.objects.annotate(search=SearchVector('name')).filter(search=SearchQuery('foo')).all()Raw Querieswithconnections["mongodb"].cursor()ascursor:doc=cursor.collections["my_collection"].find_one()assertisinstance(doc["_id"],ObjectId)