Django의 migrations 문제 및 데이터베이스 충돌. 특정 마이그레이션들이 서로 의존 관계가 맞지 않아 충돌 발생.
문제 요약:
migrations 실행 중 InconsistentMigrationHistory 오류가 발생함. report와 attendance) 간의 migration 의존성 충돌 문제.report 앱의 마이그레이션이 attendance 앱의 마이그레이션에 의존하지만, 두 마이그레이션 간 순서가 맞지 않아 오류가 발생함.오류 메시지:
django.db.migrations.exceptions.InconsistentMigrationHistory마이그레이션 충돌 문제 해결:
attendance 앱의 마이그레이션 파일을 삭제하여 마이그레이션 상태를 초기화함.python manage.py migrate attendance zero 명령어로 마이그레이션 초기화 시도. report 앱과 attendance 앱 간의 마이그레이션 순서를 맞추기 위해, attendance 앱의 마이그레이션이 먼저 적용되도록 설정.이미 존재하는 테이블 삭제:
sqlite3.OperationalError: table "report_membercheck" already exists라는 메시지에 따라, 데이터베이스 쉘에 접속하여 이미 존재하는 테이블을 직접 삭제함.report_membercheck)을 삭제한 후 마이그레이션을 다시 실행하여 문제 해결.python manage.py dbshell을 통해 데이터베이스 쉘에 접속.DROP TABLE report_membercheck; 명령어로 테이블을 삭제.정상적인 마이그레이션 완료:
attendance와 report 앱의 migration을 성공적으로 수행하여 데이터베이스 구조 충돌 문제를 해결함.report 앱의 마이그레이션을 정상적으로 수행했음에도 불구하고, PostgreSQL 데이터베이스에 report 관련 테이블이 생성되지 않는 문제가 발생.마이그레이션 파일 확인 및 재실행:
report 앱의 마이그레이션 상태를 확인 (python3 manage.py showmigrations report).SQL로 마이그레이션 파일 변환 (sqlmigrate 사용):
python3 manage.py sqlmigrate <app_name> <migration_number> 명령어를 사용하여, 마이그레이션 파일이 실제로 어떤 SQL 명령어를 수행하는지 확인.python3 manage.py sqlmigrate report 0001PostgreSQL 수동 테이블 생성:
sqlmigrate 명령어로 생성된 SQL 스크립트를 복사하여 PostgreSQL에 수동으로 실행.report 앱에 필요한 테이블을 PostgreSQL에 생성.report_membercheckreport_commentreport_usercheck외래키 및 인덱스 수동 생성:
문제 해결:
report 앱의 테이블이 수동으로 생성되었으며, Django에서 해당 테이블을 정상적으로 사용할 수 있음.python3 manage.py sqlmigrate 명령어를 통해 마이그레이션 파일을 SQL로 변환하고, 이를 수동으로 PostgreSQL에 적용.sqlmigrate 명령어 사용 방법python3 manage.py sqlmigrate <app_name> <migration_number>report 앱의 테이블이 PostgreSQL에서 정상적으로 생성되지 않는 문제 발생. Django의 자동 마이그레이션 기능을 사용하여 테이블을 생성하지 못하는 상황이 발생했음.migrate 명령어가 정상적으로 실행되었으나, 테이블은 생성되지 않음.수동으로 테이블 생성:
python3 manage.py sqlmigrate report 0001_initial 명령어를 통해 SQL 생성 쿼리를 추출.report_comment, report_membercheck, report_usercheck 테이블을 생성.ORM 작동 확인:
from report.models import MemberCheck
MemberCheck.objects.all() # ORM을 통해 데이터 조회테이블 관계 설정:
ALTER TABLE "report_membercheck" ADD CONSTRAINT "report_membercheck_name_id_3247e6db_fk_attendance_member_name" FOREIGN KEY ("name_id") REFERENCES "attendance_member" ("name") DEFERRABLE INITIALLY DEFERRED;결과:
Network Error가 발생하는 이슈.settings.py 파일에서 CORS_ALLOWED_ORIGINS에 React 앱의 주소를 추가하여 문제를 해결.CORS_ALLOW_CREDENTIALS를 True로 설정하여 자격 증명을 허용.CORS_ALLOWED_ORIGINS = [
"http://localhost:3000", # React 앱의 주소
"http://poko-dev.com", # 도메인 이름 (http 사용)
"https://poko-dev.com", # 도메인 이름 (https 사용)
]
CORS_ALLOW_CREDENTIALS = True문제점: HTTP 요청(GET, POST, PATCH 등)에 따라 응답하는 데이터의 필드를 다르게 처리할 필요가 있음.
해결 과정:
get_serializer_class 메서드를 이용해 요청 메서드에 따라 다른 Serializer를 반환하도록 구현.MemberSerializer를, POST나 PATCH 요청에는 FullMemberSerializer를 사용하도록 로직을 분리.class MembersViewSet(ModelViewSet):
serializer_class = MemberSerializer
def get_queryset(self):
user = "teacher1@example.com"
return Member.objects.filter(teacher__email=user)
def get_serializer_class(self):
if self.action in ["list", "retrieve"]:
return MemberSerializer
elif self.action in ["update", "create"]:
return FullMemberSerializer
return super().get_serializer_class()
MemberSerializer: id와 name만 반환.FullMemberSerializer: 모든 필드를 처리.AttendanceChart.js에서 useMemo와 reduce 함수를 사용하여 학생 정보와 출석 데이터를 각각 매핑.const dataSource = useMemo(() => {
return students.map(student => {
const studentAttendance = data.reduce((acc, dateEntry) => {
acc[dateEntry.date] = dateEntry.attendance[student.id];
return acc;
}, {});
return {
key: student.id,
name: student.name,
...studentAttendance,
};
});
}, [data, students]);attendance 필드를 CharField에서 BooleanField로, date 필드를 DateTimeField에서 DateField로 변경하면서 기존 데이터를 유지하고 변환해야 함.True, "결석"을 False로 변환하고, DateTime에서 Date만 남겨서 데이터 변환.def convert_attendance_and_date(apps, schema_editor):
Attendance = apps.get_model("attendance", "Attendance")
for record in Attendance.objects.all():
if record.attendance == "출석":
record.attendance = True
elif record.attendance == "결석":
record.attendance = False
record.date = record.date.date() # DateTime에서 Date만 추출
record.save()문제점: Django API에서 데이터를 받아온 후, React UI에서 각 학생의 출석 정보가 올바르게 표시되지 않는 문제.
해결 과정:
AttendanceViewSet에서 list 메서드를 수정해 데이터를 구조화.def list(self, request, *args, **kwargs):
queryset = self.get_queryset()
attendance_data = defaultdict(dict)
for record in queryset:
date_str = record.date.strftime("%Y-%m-%d")
attendance_data[date_str][record.name.id] = record.attendance
response_data = [
{"date": date, "attendance": attendance}
for date, attendance in attendance_data.items()
]
return Response(response_data)