django - bulk_create으로 csv파일 올리기

whybein·2020년 2월 19일
0

django

목록 보기
6/13
post-thumbnail

https://docs.djangoproject.com/en/3.0/ref/models/querysets/#bulk-create

다량의 데이터를 한번에 데이터베이스에 넣을 때 장고에서는 bulk_create을 사용합니다. bulk_create을 사용하기 위해서는 모델명(필드명1=밸류, 필드명2=밸류 ...)를 요소로 하는 리스트가 필요합니다. csv 파일의 데이터를 가지고 사용하는 법을 정리해 보겠습니다. 모델링 했던 스타벅스 데이터의 실제 제품 정보를 넣어보려고 합니다.

>>> Entry.objects.bulk_create([
...     Entry(headline='This is a test'),
...     Entry(headline='This is only a test'),
... ])

 


1. CSV 파일 준비

 

필드명은 제거하고 쉼표형식으로 구분된 csv파일을 준비합니다.

나이트로 바닐라 크림,우유,75,2,1,20,10,245,(url)
나이트로 쇼콜라 클라우드,우유,55,2,1,20,7,245,(url)
...

 


2. bulk_create 실행 코드


python manage.py shell
# shell로 입장합니다.

>>> import csv
>>> from product.models import Product
# 데이터를 넣을 모델을 불러옵니다.

>>> hand = open('folder/data.csv')
>>> reader = csv.reader(hand)
# csv 파일을 읽고 변수에 저장합니다.

>>> print(reader)
<_csv.reader object at 0x7fbe2b77d350>
# 아직은 객체 상태입니다.

>>> bulk_list = []
>>> for row in reader:
...     bulk_list.append(Product(
...             name=row[0],
...             alergy=row[1],
...             nutrition1=row[2],
...             nutrition2=row[3],
...             nutrition3=row[4],
...             nutrition4=row[5],
...             nutrition5=row[6],
...             nutrition6=row[7],
...             img_thumb=row[8]))
...

# 여기서 row는 `나이트로 바닐라 크림,우유,75,2,1,20,10,245,(url)` 가 됩니다.
# 모델의 필드명에 해당되는 순서로 값을 매칭시켜 bulk_list에 추가합니다.


>>> print(bulk_list)
[<Product: Product object (None)>, ... <Product: Product object (None)>]
# Product 모델에 들어갈 준비가 됐습니다.

>>> Product.objects.bulk_create(bulk_list)
[<Product: Product object (None)>, ... <Product: Product object (None)>]
# bulk_create을 실행시킵니다.

>>> Product.objects.values()
<QuerySet [{'id': 2, 'main_category_id_id': None, 'sub_category_id_id': None, 'name': '나이트로 바닐라 크림', 'name_en': None, 'desc': '', 'desc_detail': None, 'theme_id_id': None, 'alergy': '우유', 'nutrition1': Decimal('75.0'), 'nutrition2': Decimal('2.0'), 'nutrition3': Decimal('1.0'), 'nutrition4': Decimal('20.0'), 'nutrition5': Decimal('10.0'), 'nutrition6': Decimal('245.0'), 'img_main': None, 'img_thumb': 'https://image.istarbucks.co.kr/upload/store/skuimg/2019/09/[9200000002487]_20190919181354811.jpg', 'begin_at': None, 'end_at': None, 'created_at': datetime.datetime(2020, 2, 19, 2, 45, 8, 231192, tzinfo=<UTC>), 'updated_at': datetime.datetime(2020, 2, 19, 2, 45, 8, 231841, tzinfo=<UTC>)}, ... ]>
# 데이터 업로드가 완료됐습니다.

 


3. bulk_create 사용시 고려할 점들

 

bulk_create을 실행하는데 있어서 고려할 점이 몇 가지 있습니다.

 

  • foreignkey로 연결되어 있는 필드의 데이터는 업로드시 오류가 납니다. 해당 필드는 제외해야 합니다. 일반 필드 업로드 후 update 기능을 이용해 foreignkey도 csv파일로 업로드 할 수 있습니다.
django.db.utils.IntegrityError: (1452, 'Cannot add or update a child row: a foreign key constraint fails...

 

  • pk(primary key)를 지정하지 않으면 마지막 생성 pk 다음 번호부터 생성됩니다. 100개의 데이터를 넣고 지우고 다시 넣으면 101번 부터 생성됩니다. 이럴 때는 pk값을 함께 넣어서 실행하거나 DB초기화(mysql truncate) 후 진행하면 됩니다.
>>> import csv
>>> from product.models import Product
>>> hand = open('folder/data.csv')
>>> reader = csv.reader(hand)
>>> bulk_list = []
>>> for row in reader:
...     bulk_list.append(Product(
...             name=row[0],
...             alergy=row[1],
...             nutrition1=row[2],
...             nutrition2=row[3],
...             nutrition3=row[4],
...             nutrition4=row[5],
...             nutrition5=row[6],
...             nutrition6=row[7],
...             img_thumb=row[8],
...		pk=row[9]))
...
>>> Product.objects.bulk_create(bulk_list)
[<Product: Product object (1)>, ... <Product: Product object (100)>]
profile
Back-End Developer

0개의 댓글