bulk_create가 있는데 왜 그랬을까

코변·2022년 6월 15일
1

개발일지

목록 보기
31/41

장고 ORM 쓰세요~ 헛짓거리 하지말고!!

우선 저번 개발일지에 csv파일을 to_sql을 통해서 바로 업로드하는 방법을 적었었다. 그러나 처음에 테스트할 때는 잘 되던게 직접 우리 프로젝트 코드에 붙이고 작업을 하려고 하니까 계속 Foreign key mismatch ~ referencing ~ 에러가 났다.

그래 오늘의 개발일지는 내가 했던 뻘짓들의 기록이다.

  1. sqlite db를 지웠다.
  • 프로젝트가 아직 배포 전이고 클라우드 db와 붙이기 전이라서 가능했던 행동이다.
  • 앞으로 이런 일이 벌어지면 절대 하지 않을 행동이다. 우선 이 행동으로 문제가 해결되지 않은 것도 있고 애초에 앞서 말한 것처럼 만약 실제 데이터가 있었다면 시도해서는 안되는 일이기 때문이다.
  1. 마이그레이션을 새로 실행했다.
  • 모든 마이그레이션 파일을 지우고 새롭게 마이그레이션을 했다. 마이그레이션은 모델의 변경을 찾아서 반영하는데 느낌이 마이그레이션 부분에서 문제가 생겼다는 느낌이 들어서 마이그레이션을 새롭게 시도했다.
  • 이 에러 메시지는 다양한 상황에서 발생하는데 스택오버플로우를 여기저기 다니던 중에 orm을 거치지 않고 db를 지우거나 변경했을 때에도 이 에러가 발생한다고 나와있었다.
  1. 다시 돌아가 내 코드를 확인했다.
  • 돌아가서 코드를 다시 뜯어보니 나는 모델어 선언한 table이름을 참조해서 db테이블을 변경했지 장고의 orm을 거쳐서 데이터를 변경하지 않았다.
  • class를 불러왔기 때문에 orm을 사용하여 csv파일을 database에 저장했다고 착각했다. 성공한 날에 기뻐했던 내 자신이 너무 안쓰럽다 미래도 모르고
  • 결국 튜터님의 도움으로 대용량 데이터를 orm을 통해서 db에 저장하는 방법인 bulk_create를 알게 되었고 코드에 적용하게 되었다.
import pandas as pd
from post.models import 모델클래스
from itertools import islice


from django.core.management.base import BaseCommand

class Command(BaseCommand):
    def handle(self, *args, **options):
        batch_size = 100
        columns = ['tag_title', 'tag_price','tag_image_url']
        df = pd.read_csv('file path' names=columns, header=0)
        objs = (모델클래스(
            tag_title = row[0],
            tag_image_url = row[2]
        ) for _, row in df.iterrows())
        while True:
            batch = list(islice(objs, batch_size))
            if not batch:
                break
            모델클래스.objects.bulk_create(batch, batch_size)

기본적으로 python manage.py 명령어를 사용하기 위해서 management폴더에 commands 폴더에 해당 python 파일을 만들고 class Command로 감싸 handle함수를 사용하는 기본 골조는 같다.

그러나 배치사이즈를 지정해주고 csv를 dataframe으로 바꿔주고 iterrows()함수를 통해서 각 로우들을 불러와 0번째의 태그타이틀 값과 2번째의 url값들을 각각 모델클래스에 칼럼값으로 넣어주었다.

그리고 장고 docs를 참고하여 각 배치사이즈를 돌면서 배치사이즈만큼의 데이터를 저장하는 코드를 작성해보았다.

결론적으로 나를 괴롭히던 referencing 에러는 사라졌고 모델을 불러오는 것도 정상적으로 작동함을 확인했다.

새로운 시도를 통해서 많은 것을 배웠다.
1. 프레임워크를 다룰 때 프레임워크에서 권장하는 사안을 잘 지켜서 사용하자.
2. 새로운 시도를 할 때는 이 시도를 하는 이유를 분명히 하자(솔직히 겉멋 들어서 이터레이터 없이 한번에 올리고 싶었다.)
3. 이터레이션을 계속해서 돌면서 저장하는게 더 오래걸릴 거라고 생각했으나 bulk_create가 더 효율적이고 빠르게 데이터를 저장한다.
4. 현실은 항상 내 생각과는 다르다. 그러니 공부하자

참조 : https://stackoverflow.com/questions/66547188/foreign-key-mismatch-error-in-django-python
참조 : https://docs.djangoproject.com/en/4.0/ref/models/querysets/

profile
내 것인 줄 알았으나 받은 모든 것이 선물이었다.

0개의 댓글