wisheasy project (3) - Django CSV 업로드 중 발생한 두 가지 에러 분석 및 해결

에러 1 — UNIQUE constraint failed

  • 발생 위치: Edges / Nodes / Lines 테이블
  • 에러 메시지
          django.db.utils.IntegrityError: UNIQUE constraint failed: edges.edge_key
          django.db.utils.IntegrityError: UNIQUE constraint failed: nodes.node_id
    

    이 에러는 데이터베이스의 기본키(Primary Key) 제약조건과 관련된 오류이다. 기본키는 각 레코드를 유일하게 식별하는 값으로, 같은 테이블 안에서는 절대 중복될 수 없다.

    (Lines 엔티티는 기본키를 잘못 설정해서 수정했다. 중복되면 안되는데 중복되게 설계해버렸었음.)

    SQLite나 MySQL과 같은 관계형 데이터베이스에서는 PRIMARY KEY 혹은 UNIQUE 제약조건이 걸린 컬럼에 이미 존재하는 값을 다시 삽입하려고 하면 무조건 IntegrityError가 발생한다.

    즉, edges 테이블의 edge_key

    nodes 테이블의 node_id 는 기본키로 설정되어 있었기 때문에 CSV 로드 시 중복 값이 삽입되면 에러가 발생한다.

  • 해결 방법

    데이터를 단순 삽입(create)하는 대신, 이미 존재하는 key는 업데이트(update) 하고 없을 경우만 생성(create) 하도록 로직을 변경하였다.

    이때 Django ORM의 update_or_create() 메서드를 활용하였다.

          obj, created = Edges.objects.update_or_create(
          edge_key=row["edge_key"],
          defaults={
              "relation": row["relation"],
              "escalator": row.get("escalator", 0),
              "out_of_order": row.get("out_of_order", 0),
              "is_escalator": row.get("is_escalator") or None,
              "source": row["source"],
              "target": row["target"],
          },
      )
    

    이를 통해 중복으로 인한 IntegrityError를 방지하였다.

에러 2 - ValueError: Field ‘is_escalator’ expected a number but got ‘0.0’

  • 에러 메세지
      ValueError: Field 'is_escalator' expected a number but got '0.0'
    
  • 원인

    이 에러는 타입 불일치(Type mismatch) 문제로, 데이터베이스 필드 타입(IntegerField)과 CSV 파일 내 값의 실제 타입이 다를 때 발생한다.

    Django는 모델 필드의 타입에 따라 엄격하게 형 변환을 수행한다. IntegerField는 정수(int) 만 허용하며, 만약 ‘0.0’이나 ‘1.0’ 같은 문자열 또는 실수형 데이터가 전달되면 DB에 삽입하기 전에 변환하지 못하고 ValueError를 발생시킨다.

    해결은 담당 팀원에게 문제 발생하는 칼럼 정수형으로 바꿔달라고 요청했다 ㅎㅎ