2011-11-09 4 views
2

병합 할 Django-ORM 관리 데이터베이스가 2 개 있습니다. 둘 다 매우 유사한 스키마를 가지고 있으며, 둘 다 auth_users뿐만 아니라 서로를 참조하는 몇 가지 다른 공유 테이블과 함께 표준 auth_users 테이블을 가지고 있습니다. 이것은 하나의 데이터베이스에 자동으로 병합하고 싶습니다.임의로 장고 모델을 자동으로 병합합니다.

이 키는 외래 키 관계 및 각 테이블의 "고유 한"레코드를 구성하는 요소에 따라 매우 간단 할 수 있습니다.

이 병합 작업을 수행 할 도구가 있는지 아는 사람 있습니까?

현재 이와 같은 것이 없으면 표준 loaddata 명령을 기반으로 내 자신의 관리 명령을 작성하려고합니다. 근본적으로 표준 dumpdata 명령을 사용하여 원본 데이터베이스에서 테이블을 내 보낸 다음 수정 된 버전의 loaddata를 사용하여 대상 데이터베이스로 "병합"합니다. 나는 데이터베이스 A와 B가 있고, 나는 데이터베이스 A를로 데이터베이스 B를 병합 할 경우

예를 들어, 나는 의사 코드에 따라 절차를 수행 할 것 :

merge_database_dst = A 
merge_database_src = B 
for table in sorted(merge_database_dst.get_redundant_tables(merge_database_src), key=acyclic_dependency): 
    key = table.get_unique_column_key() 
    src_id_to_dst_id = {} 
    for record_src in merge_database_src.table.objects.all(): 
     src_key_value = record_src.get_key_value(key) 
     try: 
      record_dst = merge_database_dst.table.objects.get(key) 
      dst_key_value = record_dst.get_key_value(key) 
     except merge_database_dst.table.DoesNotExist: 
      record_dst = merge_database_dst.table(**[(k,convert_fk(v)) for k,v in record_src._meta.fields]) 
      record_dst.save() 
      dst_key_value = record_dst.get_key_value(key) 
     src_id_to_dst_id[(table,record_src.id)] = record_dst.id 

convert_fk() 함수는 src_id_to_dst_id 인덱스를 사용하여 소스 테이블의 외래 키 참조를 대상 테이블의 해당 ID로 변환합니다.

요약하면, 알고리즘은 부모를 먼저 반복하면서 종속성 순서로 병합 할 테이블을 반복합니다. 따라서 auth_users와 mycustomprofile 테이블을 병합하려면 auth_users에 종속적인데, 'auth_users', 'mycustomprofile']을 반복합니다.

각 병합 된 테이블에는 보편적으로 고유 한 레코드 (즉, "키")를 나타내는 열의 조합을 나타내는 일종의 표시기가 필요합니다. auth_users의 경우 "username"및/또는 "email"열일 수 있습니다.

데이터베이스 B의 키 값이 A에 이미있는 경우 레코드는 B에서 가져 오지 않지만 A의 기존 레코드 ID는 기록됩니다.

데이터베이스 B의 키 값이 A에 없으면 B에서 레코드를 가져오고 새 레코드의 ID를 기록합니다.

이전에 기록 된 ID를 사용하여 B의 특정 레코드에 대한 외래 키 참조를 A의 새로운 병합/기존 레코드에 매핑하는 방법을 설명하는 매핑이 만들어집니다. 향후 레코드가 A로 병합 될 때이 매핑은 외래 키를 변환하는 데 사용됩니다.

임포트 된 레코드가 dumpdata에 포함되지 않은 테이블을 참조하는 일부 경우를 상상할 수 있습니다. 이로 인해 전체 가져 오기가 실패 할 수 있으므로 가져 오기를 시뮬레이트하여 모든 항목을 보장하려면 일종의 "dryrun"옵션이 필요합니다. FK 참조는 번역 될 수 있습니다.

실용적인 접근 방법 인 것 같습니까? 더 좋은 방법이 있습니까?

편집 : 이것은 내가 찾고있는 것이 아니지만 다른 사람들이 흥미로울 것이라고 생각했습니다. Turbion project에는 동일한 데이터베이스 내의 다른 Django 모델에있는 동등한 레코드간에 변경 사항을 복사하는 메커니즘이 있습니다. 두 장고 모델 사이에 번역 레이어 (예 : merging.ModelLayer)를 정의하여 작동하므로 사용자 [email protected]의 프로필에서 "www"필드를 업데이트하면 사용자의 "url"필드가 자동으로 업데이트됩니다 [email protected]의 otherprofile.

내가 찾고있는 기능은 약간 다르다. 드문 경우지만 전체 (또는 부분) 데이터베이스 스냅 샷을 병합하려는 경우 loaddata 관리 명령의 방식과 비슷하다.

답변

1

와우. 이것은 복잡한 일이 될 것입니다. 즉 :

프로젝트의 요구 사항을 올바르게 이해하면 South에서 데이터 이전을 사용하여 수행 할 수 있습니다. 그렇다고해도 나는 그것이 농담이 될 것이라고 말하면 거짓말을합니다.

내 추천은 - 이것은 주로 귀하의 질문에 가정의 앵무새이지만, 나는 그것을 분명히하고 싶습니다 - 당신은 하나의 "마스터"테이블을 가지고 있으며, 다른 테이블이 추가되었습니다. 따라서 테이블 A는 기존의 모든 레코드를 유지하고 B에서 추가 된 레코드 만 가져옵니다. B는 A에 추가 내용을 제공하고 완료되면 B가 삭제됩니다.

실제 작업이 이보다 훨씬 복잡하기 때문에 샘플 코드를 작성하는 것을 주저하지만 어쨌든 올바른 방향으로 시도해 보겠습니다.

이 A를 A의 B에 모두하지 마이그레이션 결국, 당신에게 당신이 다음 다른 방법 이전으로 확인할 수 있습니다 중복 예상된다 조식, 테이블을 떠날 것이다 ... 같은 것을 고려 삭제.

내가 말했듯이이 샘플은 완전하지는 않습니다. 이 길을 가기로 결정했다면 South documentation으로 시간을 보내고 특히 data migrations을 확인하십시오.

그건 제 2 ¢입니다. 희망이 도움이됩니다.

+0

감사합니다. 내가하고 싶은 일을 정확히 이해 한 것 같습니다. 그러나 데이터 마이그레이션 기능을 병합을 수행 할 때마다 재생성해야하는 "일회성"으로 간주하기 때문에 South를 배제했습니다. – Cerin

+0

"병합 수행"이란 의미를 이해하지 못합니다. 다른 테이블을 말하는거야? 그렇다면 맞습니다. 동일한 테이블을 병합한다는 것은 나중에 수동으로 수행하는 것보다 훨씬 쉽게 수행 할 수 있습니다 (이후 번호로 복사하거나 수행하지 않음으로써 마이그레이션을 다시 수행 할 수 있음). 나는 남한이 당신이하고있는 일을 위해 완벽하게 구축되었다고 말하는 것이 아니라, 남한과 함께이 일을 훨씬 더 쉽게 할 수 있습니다. –

관련 문제