Frappe Fixture — migrate마다 데이터를 덮어쓰는 시스템
general
개념
Frappe에서 fixture는 JSON 파일로 DB 레코드를 버전관리하는 시스템. bench migrate 할 때마다 JSON → DB로 동기화된다.
hooks.py에 fixture 선언 → bench export-fixtures로 JSON 생성
→ bench migrate 시 JSON → DB로 삽입/업데이트
설정 방법
hooks.py에서 선언:
# 전체 문서 export
fixtures = ["Email Template"]
# 필터로 특정 문서만
fixtures = [
{
"doctype": "Email Template",
"filters": [["name", "in", ["invite", "welcome"]]]
}
]
bench export-fixtures # DB → JSON 파일로 추출
bench migrate # JSON → DB로 동기화
파일 위치
앱이름/
fixtures/
email_template.json # DocType 이름의 snake_case
JSON 안에 해당 DocType의 레코드들이 배열로 들어있다.
함정: UI 수정이 migrate에서 날아감
- UI에서 Email Template "invite"의 HTML을 수정
bench migrate실행- fixture JSON의 원본 버전으로 덮어쓰기됨
- UI에서 수정한 내용 사라짐
이게 의도된 동작이다. fixture는 "이 데이터는 코드가 관리한다"는 선언이니까.
해결 패턴
1. fixture에서 제외
사용자가 UI에서 커스텀할 문서는 fixture에서 빼고, 초기 세팅은 after_install 훅으로 처리:
# hooks.py
fixtures = [
{
"doctype": "Email Template",
"filters": [["name", "not in", ["invite"]]] # invite는 제외
}
]
2. fixture JSON을 수정
UI가 아니라 JSON 파일을 직접 수정하고 커밋. 이러면 migrate 후에도 최신 버전이 반영됨.
3. after_migrate 훅으로 조건부 생성
# hooks.py
after_migrate = ["앱이름.setup.create_default_templates"]
def create_default_templates():
if not frappe.db.exists("Email Template", "invite"):
# 없을 때만 생성, 있으면 건드리지 않음
frappe.get_doc({...}).insert()
use_html 필드 주의
Email Template에는 response와 response_html 두 필드가 있다.
- UI에서 HTML 편집기로 저장하면
use_html=1+response_html에 저장 - fixture JSON은 보통
response필드에 저장
코드에서 템플릿 본문을 읽을 때:
template = frappe.get_doc("Email Template", "invite")
body = template.response_html or template.response
response만 읽으면 UI에서 HTML로 작성한 내용이 무시된다.
정리
| 상황 | 방법 |
|---|---|
| 코드가 관리하는 데이터 | fixture로 관리, UI 수정 금지 |
| 사용자가 커스텀하는 데이터 | fixture에서 제외 |
| 초기값만 필요한 데이터 | after_install/after_migrate로 조건부 생성 |