在两个django服务器之间同步数据

时间:2013-06-28 18:31:54

标签: database django django-fixtures django-extensions

我有一个中央Django服务器,其中包含我在数据库中的所有信息。我想要第二个Django服务器,在第二个数据库中包含该信息的子集。我需要一种防弹方式来有选择地在两者之间同步数据。

  • 辅助Django需要在特定时间从主数据中提取其数据子集。必须按某些字段过滤子集。
  • 辅助Django必须偶尔将其数据推送到主数据库。
  • 理想情况下,双向同步会为每个模型保留最近修改过的对象。

我正在考虑使用TimeStampedModel(来自django-extensions)或添加我自己的DateTimeField(auto_now = True),以便每个对象存储其上次修改时间。然后,可能是一种机制,用于从一个数据库转储数据并将其加载到另一个数据库中,以便只保留最近修改过的对象。

我正在考虑的可能性是django的dumpdata,django-extensions dumpscript,django-test-utils makefixture或者django-fixture magic。需要考虑很多,所以我不确定要走哪条路。

1 个答案:

答案 0 :(得分:2)

这是我的解决方案,符合我的所有要求:

  1. 在所有模型上实施natural keys和唯一约束
    • 允许以独特方式引用每个对象而不使用主键ID
  2. 在django-extensions中对TimeStampedModel中的每个模型进行Sublcass
    • 添加自动更新的createdmodified字段
  3. 创建用于导出的Django管理命令,该命令过滤数据子集并使用自然键对其进行序列化

    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. 创建用于导入的Django管理命令,该命令读取序列化文件并按如下方式遍历对象:

    • 如果数据库中不存在该对象(通过自然键),则创建它
    • 如果对象存在,请检查modified时间戳
    • 如果导入的对象较新,请更新字段
    • 如果导入的对象较旧,请不要更新(但打印警告)
  5. 代码示例:

    # 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