代码之家  ›  专栏  ›  技术社区  ›  Benjamin Wohlwend

django multidb:写入多个数据库

  •  4
  • Benjamin Wohlwend  · 技术社区  · 14 年前

    使用django multidb,编写 router 它运行主/从基础设施。但是有没有可能写一个路由器 到多个数据库?我的用例是一组项目,它们都在同一个域上运行。为了避免用户在每个站点上注册/登录,我想同步 contrib.auth contrib.sessions 桌子。对于django multidb,这是可能的,还是应该研究数据库系统的复制特性(在我的例子中是mysql)?

    3 回复  |  直到 13 年前
        1
  •  4
  •   jsh    13 年前

    我现在正在研究一个Django Sharding模式。

    我看着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将尝试使用该对象所在的同一个数据库(根据Django的典型操作方式,显然是有原因的)。

    1. 另一个想法:

    从您引用的django multidb页面上的示例中,我想知道下面的内容是否有效:

    他们的样本代码:

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

    可能的修改:

    def允许同步数据库(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
  •  5
  •   mouad    14 年前

    我认为您最好实现SSO或OAuth服务

    但是,如果希望在两个数据库之间同步表用户,并且使用自己的用户模型,则可以这样做

    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):
          ....
    

    希望这会有所帮助:)

        3
  •  1
  •   Community CDub    7 年前

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

    我试过穆拉德的回答,但我不能让班级装饰工工作…在我看来,这个解决方案不允许在模型中有自定义的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)