【问题标题】:Django Celery and multiple databases (Celery, Django and RabbitMQ)Django Celery 和多个数据库(Celery、Django 和 RabbitMQ)
【发布时间】:2011-07-24 12:50:15
【问题描述】:

是否可以设置不同的数据库与 Django Celery 一起使用?

我有一个配置多个数据库的项目,不希望 Django Celery 使用默认的。

如果我仍然可以使用 django celery 管理页面并读取存储在这个不同数据库中的结果,我会很好:)

【问题讨论】:

    标签: django rabbitmq celery django-celery


    【解决方案1】:

    是的,你可以。

    首先:您可以设置两个数据库并为 celery 任务明确指定第二个数据库(例如obj.save(using='second')

    或创建第二个settings.py 用于芹菜:

    ./manage.py celeryd --settings_second
    

    【讨论】:

    • 对于第二个选项 - 如果我决定使用其他设置文件,那么我认为我的 celery django 管理页面看起来不会是正确的数据库:(
    • 什么是任务将完全相同,然后我只需要根据当前使用的站点在单独的数据库中运行(不能使用 obj.save(using='second' ) 选项 ) ?我正在尝试开发这个 SaaS 产品,每个客户端都将具有相同的功能,但使用不同的子域。
    【解决方案2】:

    应该可以使用 Django 数据库路由器为 django-celery 模型建立一个单独的数据库:

    https://docs.djangoproject.com/en/1.4/topics/db/multi-db/#automatic-database-routing

    我没有专门用 django-celery 对此进行测试,但如果由于某种原因它不起作用,那么它是 django-celery(或 Django 本身)中的一个错误,应该修复。

    你的路由器看起来像这样:

    class CeleryRouter(object):
        "Route Celery models to separate DB."
        APPS = (
            'django',  # Models from kombu.transport.django, if you're using Django as a message transport.
            'djcelery',
        )
        DB_ALIAS = 'celery'
    
        def db_for_read(self, model, **hints):
            if model._meta.app_label in self.APPS:
                return self.DB_ALIAS
            return None
    
        def db_for_write(self, model, **hints):
            if model._meta.app_label in self.APPS:
                return self.DB_ALIAS
            return None
    
        def allow_relation(self, obj1, obj2, **hints):
            if (obj1._meta.app_label in self.APPS and
                obj2._meta.app_label in self.APPS):
                return True
            return None
    
        def allow_syncdb(self, db, model):
            if db == self.DB_ALIAS:
                # Only put models from APPS into Celery table (and south for
                # migrations).
                return model._meta.app_label in self.APPS + ('south',)
            elif model._meta.app_label in self.APPS:
                # Don't put Celery models anywhere else.
                return False
            return None
    

    然后将其添加到您的设置中:

    DATABASE_ROUTERS = ['path.to.CeleryRouter']
    

    【讨论】:

    • 你确定这个APPS = ( ... 'django' ... ) 想,我不明白吗? :(