【问题标题】:Decorator to override save to write in Multiple databases装饰器覆盖保存以写入多个数据库
【发布时间】:2018-11-21 15:20:00
【问题描述】:

我计划在我们的应用程序中使用模型写入两个数据库。我想写一个装饰器来为所有模型使用它。我正在使用下面的代码

class save_multi_db(models.Model):
    def __call__(self, cls):
        class Wrapped(cls):
            def save(self, *args, **kwargs):
                redis_connection = redis.Redis(connection_pool=settings.MAPPING_REDIS_POOL)
                if int(redis_connection.get('write_to_db')):
                     super(cls, self).save(using='prod')
                     super(cls, self).save(using='default')
                else:
                     return cls.save()
        return Wrapped

我有下面这样的课程

@save_multi_db()
class ModelA(models.Model):
    #model A 

class MobelB(ModelA):
    class Meta:
        db_table = 'name'

如果我将装饰器用于单个模型,这完全可以正常工作。但如果我在另一个模型上使用装饰器,则在同一个 models.py 中。我收到以下错误

(fields.E300) Field defines a relation with model 'Wrapped', which is either not installed, or is abstract.

【问题讨论】:

  • 我认为在模型级别对此进行修补是相当奇怪的,因为通常模型对所使用的数据库是不变的。你可能会更好地实现数据库路由
  • 乍一看,在我看来,您构建的 mutliple 类都具有相同的名称,因此 Django 感到困惑。此外,这个Wrapped 可能会失败,以防它已经被包装一次。
  • 我希望它必须在某个时候编写两个数据库
  • 就像之前说的,模型层不是做数据库路由的好地方。 .save(..) 并不总是被调用。例如ModelA.objects.update(foo=F('bar')) 无论如何都会绕过.save(..)。所以你最好尝试实现一个数据库路由器。

标签: python django django-models decorator python-decorators


【解决方案1】:

如果你真的想通过覆盖Model.save()来解决问题,不要使用类装饰器,而是使用抽象基类并覆盖save()

class Multisave(models.Model):
    def save(self, *args, *kw):
        # your code here

    class Meta:
        abstract = True


class ModelA(Multisave):
   # ...

但正如 Willem Van Onsem 所提到的,这对于绕过 Model.save() 的操作将无法正常工作,因此使用数据库路由器肯定是一个更安全的解决方案。

【讨论】:

  • 我们可以根据配置使用 DB 路由器写入两个数据库吗?
猜你喜欢
  • 1970-01-01
  • 2022-09-29
  • 2014-07-21
  • 2017-07-12
  • 1970-01-01
  • 2017-04-09
  • 2010-12-11
  • 2013-01-19
  • 2021-12-27
相关资源
最近更新 更多