Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mixing PostgreSQL and MongoDB (as Django backends)

I'm thinking about shifting my site's backend to Mongo from Postgres for performance reasons, but key parts of the site rely on the GeoDjango models to calculate distances between objects in the real world (and so on).

Would it be feasible to have most of the site running on Mongo but those key areas using Postgres for storage? Is this painful and / or error-prone? Is there an all-Mongo solution I'm missing?

Any light you can shed on these matters for me would be much appreciated.

like image 497
Alistair Avatar asked Apr 21 '11 11:04

Alistair


People also ask

Does Django work well with MongoDB?

Django, the most popular Python web framework, is an ideal tool to build secure and easy-to-maintain applications using MongoDB. Using MongoDB with Django is advantageous because: Every second, more and more unstructured data is generated from various sources like chats, real-time streams, feeds, and surveys.

Is PostgreSQL good for Django?

We've seen how Django is the most capable web framework, and PostgreSQL is the most robust and dependable RDBMS. As a developer, you can leverage the versatility of PostgreSQL to work with almost any type of data and the unbeatable features of Django to develop fast and secure web applications.


1 Answers

Since Django 1.2, you can define multiple datbase connections in your settings.py. Then you can use database routers to tell Django which database to go to, transparently for your application.

Disclaimer: this is how I think it should work, I have never used MongoDB in Django, nor have I tested that my code actually works. :)

settings.py

DATABASES = {
    'default': {
        'ENGINE': 'django_mongodb_engine',
        'NAME': 'mydata',
        ...
    }
    'geodata' {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'geodata',
        ...
    }
}

DATABASE_ROUTERS = ['path.to.ModelMetaRouter']

Models

Then add custom Meta variables to your geo-tables, to override their database. Don't add this attribute to models that are supposed to go to the default database.

class SomeGeoModel(models.Model):
    ...
    class Meta:
        using = 'geodata'

Database router

And write a database router to direct all models that have the using meta attribute set, to the appropriate connection:

class ModelMetaRouter(object):
    def db_for_read(self, model, **hints):
        return getattr(model._meta, 'using', None)

    def db_for_write(self, model, **hints):
        return getattr(model._meta, 'using', None)

    def allow_relation(self, obj1, obj2, **hints):
        # only allow relations within a single database
        if getattr(obj1._meta, 'using', None) == getattr(obj2._meta, 'using', None):
            return True
        return None

    def allow_syncdb(self, db, model):
        if db == getattr(model._meta, 'using', 'default'):
            return True
        return None
like image 96
intgr Avatar answered Sep 19 '22 07:09

intgr