Django MultiDB: запись в несколько баз данных - PullRequest
4 голосов
/ 28 октября 2010

С помощью Django multidb довольно просто написать маршрутизатор , который запускает инфраструктуру master / slave. Но возможно ли написать маршрутизатор, который записывает в несколько баз данных? Мой вариант использования - это коллекция проектов, все запущенные в одном домене. Чтобы пользователи не регистрировались и не входили на каждый сайт, я хотел бы синхронизировать таблицы contrib.auth и contrib.sessions. Это возможно с Django multidb или я должен изучить возможности репликации системы баз данных (MySQL в моем случае)?

Ответы [ 3 ]

6 голосов
/ 28 октября 2010

я думаю, вам будет лучше внедрить службу SSO или OAuth

но если вы хотите синхронизировать пользователей таблиц между двумя базами данных и если вы используете свою собственную UserModel, вы можете сделать что-то вроде этого

class MyUser(models.Model):
    name = models.CharField(max_length=100)
    user = models.ForeignKey(User, unique=True)


    def save(self, ...): # ALL the signature
        super(MyUser, self).save(using='database_1')
        super(MyUser, self).save(using='database_2')

вы также можете использовать декоратор, например, так же, как вы можете использовать его для синхронизации других таблиц:

def save_multi_db(model_class):

    def save_wrapper(save_func): 
        def new_save(self, *args, **kws):
            super(model_class, self).save(using='database_1')
            super(model_class, self).save(using='database_1')
        return new_save

    func = getattr(model_class, 'save')
    setattr(model_class, 'save', save_wrapper(func)) 

    return save_wrapper

# and use it like this:

@save_multi_db
class MyUser(models.Model):
      ....

Надеюсь, это поможет :)

4 голосов
/ 29 марта 2011

Я сейчас работаю над схемой шардинга Django.

Я посмотрел на роутер Django, но решил свернуть свой.

некоторые мысли по вашей проблеме:

  1. Одна идея состоит в том, чтобы использовать одну базу данных, а затем копировать соответствующие данные с помощью сигналов Django при сохранении.

что-то вроде--

import settings.databases as dbs_list

def post_save_function(UserModel):
     for db in dbs_list:
          UserModel.save(using=db,force_insert=True)

сохранение пользовательских объектов (по крайней мере, в модели с одной БД), по-видимому, сохраняет данные сеанса, аутентификации и т. Д. Под колпаком с помощью различных магий, происходящих внутри django.contrib, поэтому есть вероятность, что вам, возможно, не придется заходить и выяснить имена и типы всех этих таблиц базы данных.

в поддержку возможности этой работы, я клянусь, я где-то недавно читал (вероятно, в одном из сообщений в блоге Алекса Гейнора), что, если у объекта есть внешний ключ, Django попытается использовать ту же БД, на которой он живет (для очевидные причины в свете того, как обычно работает Джанго).

  1. другая идея:

из примера на странице Django multiDB, на которую вы ссылались, мне интересно, сработает ли что-то вроде следующего:

их пример кода:

def allow_syncdb(self, db, model):
        "Explicitly put all models on all databases."
        return True

возможная модификация:

def allow_syncdb (self, db, model):

    if isinstance(model,User):
         return True

    elif isinstance(model,Session):
         return True

    else:
         ''' something appropriate --
             whatever your sharding schema is for other objects '''

Если посмотреть еще раз, этот код, вероятно, будет более полезен как функция "db_for_write". но вы поняли.

нет никаких сомнений в том, что другие типы моделей, которые вы должны были бы добавить, чтобы сделать эту работу (все, что является подлинным, обширно).

удачи! Надеюсь, это поможет вам.

Мне интересны ваши выводы и комментарии!

ДБ

1 голос
/ 17 июня 2011

Во-первых, я думаю, что вам нужно больше SSO-фреймворка, например в этом посте

Я попробовал ответ Муада, но не смог заставить работать декоратор класса ... Имне кажется, что это решение не позволяет настраивать save () в моделях.

Более подходящий для моих потребностей, я определил настраиваемый родовой класс и просто переопределил функцию save ().

class MultiDbModel(models.Model):
    class Meta:
        abstract = True

    def save(self, *args, **kwarg
        for dbname in settings.DATABASES:
            super(MultiDbModel, self).save(using=dbname)

А потом:

class MyObject(MultiDbModel):
    [...]
    def save(self, *args, **kwargs):
        [custom save]
        super(MyObject, self).save(args, kwargs)
...