使用Django

时间:2019-02-06 12:47:04

标签: python django postgresql database-replication django-signals

我不想使用数据库的内置功能进行复制。因此,我试图在djnago应用程序级别上设置数据库复制(仅addupdatedelete操作)。
我已经在settings.py

中配置了multi-db

所以设置文件看起来像

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': config['DB_NAME'],
        'USER': config['DB_USER'],
        'PASSWORD': config['DB_PASSWORD'],
        'HOST': config['DB_HOST'],
        'PORT': config['DB_PORT'],
    },
    'tableau': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'tableau',
        'USER': 'postgres',
        'PASSWORD': 'postgres',
        'HOST': 'localhost',
        'PORT': 5432,
    },
}

我能够像

一样从两个数据库中读写
from myapp.model import People

# writing to db
People.objects.create(name='alok', location='India') # onto defalut db
People.objects.using('tableau').create(name='alok', location='India') # onto replication db

# reading from db
People.objects.filter(name='alok') # from default db
People.objects.using('tableau').filter(name='alok') # from replication db

我的要求是使两个数据库保持同步(它们应该具有相同的数据)。我想使用django.db.models.signals.post_savedjango.db.models.signals.post_delete

这样的djnago signals使两个数据库保持同步

例如,如果我在跑步

People.objects.create(name='alok2', location='India2')

然后,此类条目也应在其他数据库中创建。
如何编写receiver function来处理这些信号?我应该在哪里保留接收器功能?

2 个答案:

答案 0 :(得分:0)

您可能应该在数据库级别配置数据库复制。

这是更可靠的,因为postgresql是为此目的而制作的。 您将在此链接上找到更多信息: https://www.postgresql.org/docs/10/high-availability.html

答案 1 :(得分:0)

我们需要创建适当的相关信号接收器功能。有些是由django本身提供的,有些是在外部模块Django Query Signals

中可用的

因此在应用目录中创建了signals.py,以保留所有接收器功能。

from django.db.models.signals import post_save, post_delete
from django.dispatch import receiver
from django_query_signals import post_update, post_bulk_create, post_get_or_create, post_update_or_create


@receiver(post_save)
def post_save_receiver(sender, instance, created, raw, using, **kwargs):
    if using == 'default':
        instance.save(using='tableau')


@receiver(post_delete)
def post_delete_receiver(sender, instance, using, **kwargs):
    if using == 'default':
        instance.delete(using='tableau')


@receiver(post_update)
def post_update_receiver(*args, **kwargs):
    received_call = kwargs['args']
    db_name = received_call['self']._db
    method = received_call['method']
    if db_name == None and method == 'update':
        received_query_set = received_call['self']
        received_query_set.using('tableau').update(**received_call['kwargs'])


@receiver(post_bulk_create)
def post_bulk_create_receiver(*args, **kwargs):
    received_call = kwargs['args']
    db_name = received_call['self']._db
    method = received_call['method']
    if db_name == None and method == 'bulk_create':
        sender = kwargs['sender']
        objs = received_call['objs']
        batch_size = kwargs['args']['batch_size']
        sender.objects.using('tableau').bulk_create(objs, batch_size=batch_size)


@receiver(post_get_or_create)
def post_get_or_create_receiver(*args, **kwargs):
    received_call = kwargs['args']
    db_name = received_call['self']._db
    method = received_call['method']
    if db_name == None and method == 'get_or_create':
        sender = kwargs['sender']
        obj = received_call['kwargs']
        defaults = received_call['defaults']
        sender.objects.using('tableau').get_or_create(**obj, defaults=defaults)


@receiver(post_update_or_create)
def post_update_or_create_receiver(*args, **kwargs):
    received_call = kwargs['args']
    db_name = received_call['self']._db
    method = received_call['method']
    if db_name == None and method == 'update_or_create':
        sender = kwargs['sender']
        obj = received_call['kwargs']
        defaults = received_call['defaults']
        sender.objects.using('tableau').update_or_create(**obj, defaults=defaults)

添加条目以在my_django_project/my_app/apps.py

中注册这些接收器功能
from django.apps import AppConfig

class MyAppConfig(AppConfig):
    name = 'my_app'

    def ready(self):
        import my_app.signals # this will load receiver functions

MyAppConfig上添加my_django_project/my_app/__init__.py

default_app_config = 'my_app.apps.MyAppConfig'

当然,您需要在django_query_signals的{​​{1}}中添加INSTALLED_APPS