Django multidb:写入多个数据库

时间:2010-10-28 09:26:55

标签: python django django-orm

使用Django multidb,编写运行主/从基础结构的router相当容易。但是有可能将写入的路由器编写到多个数据库中吗?我的用例是一组项目,都在同一个域上运行。为了节省用户在每个站点上注册/登录,我想同步contrib.authcontrib.sessions表。这是可能的Django multidb还是我应该研究数据库系统的复制功能(在我的情况下是MySQL)?

3 个答案:

答案 0 :(得分:6)

我认为您将更好地实施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):
      ....

希望这会有所帮助:)

答案 1 :(得分:4)

我正在研究Django分片架构。

我看着Django路由器,但决定推出自己的路由器。

关于你的问题的一些想法:

  1. 一个想法是使用一个数据库,然后通过在保存后使用Django信号复制适当的数据。
  2. 类似的东西 -

    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内部发生的各种魔法保存会话,身份验证等数据,因此您可能无需进入并找出所有这些数据库表的名称和类型。

    为了支持这种工作的可能性,我发誓我最近在某处读过(可能在Alex Gaynor的一篇博客文章中),如果一个对象有一个外键,Django会尝试使用该对象所在的同一个DB(用于鉴于Django通常的运作方式,显而易见的原因)。

    1. 另一个想法:
    2. 从您引用的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”函数可能会更有用。但是你明白了。

      毫无疑问,您必须添加其他类型的模型才能使其工作(所有auth的东西,这是广泛的)。

      祝你好运!希望这在某种程度上有所帮助。

      我对你的发现和评论感兴趣!

      JB

答案 2 :(得分:1)

首先,我认为您需要的是更多的SSO框架,例如in this post

我尝试了mouad的答案,但我无法让类装饰工作......而且在我看来这个解决方案不允许在模型中使用自定义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)