两个Django服务器之间如何同步数据

4
我有一个中央的Django服务器,包含了所有信息的数据库。我想要有第二个Django服务器,它包含第二个数据库中的一部分信息。我需要一种可靠的方式来在这两个服务器之间选择性地同步数据。
  • 次要的Django将需要在某些时间从主服务器中提取其子集数据。该子集将必须通过特定字段进行过滤。
  • 偶尔,次要的Django将需要将其数据推送到主服务器。
  • 理想情况下,双向同步将保持每个模型最近修改的对象。
我考虑使用TimeStampedModel(来自django-extensions)或添加自己的DateTimeField(auto_now=True),以便每个对象都存储其上次修改的时间。然后,也许有一种机制可以将数据从一个数据库转储并加载到另一个数据库中,以便只保留最近修改的对象。
我正在考虑的可能性是django的dumpdata,django-extensions dumpscript,django-test-utils makefixture或者django-fixture magic。这需要仔细思考,所以我不确定应该走哪条路。

1
你能在数据库层面上做到吗?(例如,如果你正在使用Postgres,则编写脚本来pg_dump/pg_restore需要的内容)如果你需要更加牢靠的东西,这可能会更加明智。 - bitgarden
在您的主Django服务器中创建一个辅助连接并将其命名为“slave”。编写一个定时运行的cron/celery脚本,使用默认连接从您的表中获取数据,并使用slave连接保存它们。参考此链接以获取更多想法:https://gist.github.com/bofh19/5887902 - boltsfrombluesky
这些方法能否通过时间戳将两个数据库同步? - Hayk Martiros
1个回答

5

这是我的解决方案,它满足了我所有的需求:

  1. Implement natural keys and unique constraints on all models
    • Allows for a unique way to refer to each object without using primary key IDs
  2. Sublcass each model from TimeStampedModel in django-extensions
    • Adds automatically updated created and modified fields
  3. Create a Django management command for exporting, which filters a subset of data and serializes it with natural keys

    baz = Baz.objects.filter(foo=bar)
    yaz = Yaz.objects.filter(foo=bar)
    
    objects = [baz, yaz]
    flat_objects = list(itertools.chain.from_iterable(objects))
    
    data = serializers.serialize("json", flat_objects, indent=3, use_natural_keys=True)
    print(data)
    
  4. Create a Django management command for importing, which reads in the serialized file and iterates through the objects as follows:

    • If the object does not exist in the database (by natural key), create it
    • If the object exists, check the modified timestamps
    • If the imported object is newer, update the fields
    • If the imported object is older, do not update (but print a warning)

代码示例:

# Open the file
with open(args[0]) as data_file:
    json_str = data_file.read()

# Deserialize and iterate
for obj in serializers.deserialize("json", json_str, indent=3, use_natural_keys=True):

    # Get model info
    model_class = obj.object.__class__
    natural_key = obj.object.natural_key()
    manager = model_class._default_manager

    # Delete PK value
    obj.object.pk = None

    try:
        # Get the existing object
        existing_obj = model_class.objects.get_by_natural_key(*natural_key)

        # Check the timestamps
        date_existing = existing_obj.modified
        date_imported = obj.object.modified
        if date_imported > date_existing:

            # Update fields
            for field in obj.object._meta.fields:
                if field.editable and not field.primary_key:
                    imported_val = getattr(obj.object, field.name)
                    existing_val = getattr(existing_obj, field.name)
                    if existing_val != imported_val:
                        setattr(existing_obj, field.name, imported_val)

    except ObjectDoesNotExist:
        obj.save()

这个工作流程的第一步是调用python manage.py exportTool > data.json,然后在另一个Django实例(或者同一个实例)上调用python manage.py importTool data.json


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接