2013-06-28 5 views
2

У меня есть центральный сервер Django, содержащий всю мою информацию в базе данных. Я хочу иметь второй сервер Django, который содержит подмножество этой информации во второй базе данных. Мне нужен пуленепробиваемый способ выборочной синхронизации данных между ними.Синхронизация данных между двумя серверами django

  • Вторичный Django должен будет вытащить подмножество данных из первичного в определенное время. Подмножество должно быть отфильтровано по определенным полям.
  • Вторичному Django придется время от времени подталкивать свои данные к первому.
  • В идеальном случае двусторонняя синхронизация сохранит самые последние измененные объекты для каждой модели.

Я думал что-то вдоль линий, имеющих используя TimeStampedModel (от Джанго-расширений) или добавить свой собственный DateTimeField (auto_now = True), так что каждый объект хранит время последнего изменения. Затем, возможно, механизм для сброса данных из одного БД и загрузки его в другой, чтобы сохранить только более недавно измененные объекты.

Возможности, которые я рассматриваю, - это dumpdata django, django-extensions dumpscript, django-test-utils makefixture или, возможно, магия django-fixture. О чем много думать, поэтому я не знаю, на какую дорогу двигаться дальше.

+1

Вы можете сделать это на уровне базы данных? (например, если вы используете postgres, написав скрипт, что pg_dump/pg_restore, что вам нужно). Если вам нужно что-то пуленепробиваемое, это может быть немного здраво. – bitgarden

+0

создайте вторичное соединение на своем основном сервере django и вызовите его slave. напишите скрипт cron/celery, который работает своевременно и получает данные из ваших таблиц с использованием подключения по умолчанию и сохраняет их с помощью подчиненного соединения. см. это для идеи https://gist.github.com/bofh19/5887902 – boltsfrombluesky

+0

Являются ли эти методы возможность синхронизации двух баз данных по метке времени? –

ответ

2

Вот мое решение, которое соответствует всем моим требованиям:

  1. Реализовать natural keys и уникальные ограничения на всех моделях
    • позволяет уникальным образом ссылаться на каждый объект без использования первичных ключей идентификаторов
  2. Sublcass каждая модель из TimeStampedModel в Джанго-расширений
    • Добавляет автоматическое обновление created и modified поля
  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 для импорта , который читается в сериализованном файле и итерации по объектам следующим образом:

    • Если объект не является exis т в базе данных (по естественному ключу), создать его
    • Если объект существует, проверьте modified временные метки
    • Если импортированный объект новее, обновите поля
    • Если импортированный объект старше, не обновлять (но выводит предупреждение)

Пример кода:

# 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.

Смежные вопросы