Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

set db per model in django

Tags:

python

django

I've been looking over django's multi-db docs. I'd like to break a few of my models out into a different db. But I really just want those models to ALWAYS live in a particular db. I don't need special routing. And writing unique routers just to say "Models A, B, and C live in database X, models D, E, and F always live in database Y".

Is there a simpler way to set defaults like this? For instance, as a model meta field?

like image 837
chrispitzer Avatar asked Jan 04 '12 22:01

chrispitzer


People also ask

Can we use 2 databases in Django?

Django's admin doesn't have any explicit support for multiple databases. If you want to provide an admin interface for a model on a database other than that specified by your router chain, you'll need to write custom ModelAdmin classes that will direct the admin to use a specific database for content.

What does Django DB models model clean () do?

clean() This method should be used to provide custom model validation and to modify attributes on your model if desired.

What is Django DB models model?

In Django, a model is a class which is used to contain essential fields and methods. Each model class maps to a single table in the database. Django Model is a subclass of django.


2 Answers

You can easily do this by appearing custom attribute to model:

class A(models.Model):
    _DATABASE = "X"

class B(models.Model):
    _DATABASE = "Y"
...

Then you need to add router. Next one will select database by _DATABASE field, and models without _DATABASE attribute will use default database, also relationships will be allowed only for default database:

class CustomRouter(object):

    def db_for_read(self, model, **hints):
        return getattr(model, "_DATABASE", "default")
        
    def db_for_write(self, model, **hints):
        return getattr(model, "_DATABASE", "default")

    def allow_relation(self, obj1, obj2, **hints):
        """
        Relations between objects are allowed if both objects are
        in the master/slave pool.
        """
        db_list = ('default')
        return obj1._state.db in db_list and obj2._state.db in db_list

    def allow_migrate(self, db, model):
        """
        All non-auth models end up in this pool.
        """
        return True  

And the last step is specifing your router in settings.py:

DATABASE_ROUTERS = ['path.to.class.CustomRouter']

Source


BTW this solution will not work if you are going to work with many-to-many relations in non-default database because relational models will not have "_DATABASE", attribute, in this case, better to use something like model._meta.app_label as filter condition in db_for_read/db_for_write

like image 54
Ivan Borshchov Avatar answered Oct 17 '22 01:10

Ivan Borshchov


There is no Meta field for this (there was one at some point but it got removed because of the limitations it introduced). You need a database router to control which objects go to what database. In your case the router should be pretty easy to implement.

like image 34
brutasse Avatar answered Oct 17 '22 03:10

brutasse