csv, json 데이터를 장고 db에 넣기

nikevapormax·2022년 6월 11일
0

TIL

목록 보기
45/116

😂 Django Project

😭 프로젝트 세팅

- csv file 준비

  • 다음과 같은 내용의 파일을 준비하였다.
  • 강의에서 사용된 파일과의 다른 점은 tag의 각 요소에 따옴표가 없다는 점이다.

- django project 생성

  • django project를 생성하기 위해 우선적으로 봐야할 것은 가상환경이다. 제아무리 터미널에 프로젝트 생성 명령어를 입력해도 가상환경이 켜져있지 않다면 프로젝트는 생성되지 않는다.
  • 아래와 같은 명령어를 입력해 가상환경을 실행해준다. (가상환경에는 django가 세팅되어 있다! 되어 있지 않다면 먼저 세팅해야 함!)
    • 폴더 이름 옆에 .을 한 칸 띄고 입력해야 현재 폴더 안에 프로젝트 폴더가 잘 생성된다.
$ conda activate WatchamovieN11Django 
$ django-admin startproject turtle_csvtojson .

  • 이제 app을 하나 생성해 django에서 사용할 model을 만들어보도록 하겠다.
$ django-admin startapp movies
  • turtle_csvtojson/settings.py에서 내가 생성한 app을 등록하는 것을 빼먹으면 안 된다.
#### 상단 생략 ####

INSTALLED_APPS = [
    'movies',
    
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

#### 하단 생략 ####
from django.db import models

# Create your models here.
class Tag(models.Model):
    class Meta:
        db_table = 'tag'
        
    name = models.CharField(max_length=70, default='')
    
class Movie(models.Model):
    class Meta:
        db_table = 'movie'
        
    movieId = models.IntegerField()
    title = models.CharField(max_length=100, default='')
    desc = models.TextField()
    image = models.CharField(max_length=100, default='')
    score = models.DecimalField(max_digits=2, decimal_places=1)
    tag = models.ManyToManyField(Tag, related_name='movies')
  • model을 생성하였으니 해당 모델을 사용하기 위한 작업을 한다.
$ python manage.py makemigrations
$ python manage.py migrate

  • 생성된 db를 확인해보자
    • 전체 db 생김새
    • 우리가 다대다 관계로 모델을 만들었기 때문에 movie_tag라는 브릿지 테이블이 형성된 것을 볼 수 있다. 또한 movie 테이블로 들어가보면 우리는 분명히 코드에는 tag를 입력했는데 해당 테이블에는 없는 것을 볼 수 있다.


😭 csv 파일 -> json 파일

  • 우리의 최종 목적은 csv 파일을 아래의 형태로 만드는 것이다.

- tag 데이터

  • 먼저 tag 데이터를 json 형식으로 만들어보도록 하겠다.
  • 내가 가지고 있는 tag에 대한 정보를 아래와 같은 json 파일로 생성한다.
[
    "Adventure",
    "Fantasy",
    "Animation",
    "Drama",
    "Horror",
    "Action",
    "Comedy",
    "History",
    "Western",
    "Thriller",
    "Crime",
    "Documentary",
    "Science Fiction",
    "Mystery",
    "Music",
    "Romance",
    "Family",
    "War",
    "TV Movie"
]
  • tag_loader.py 생성
    • pk 값은 자동으로 생성해주니까 내가 꼭 만들어야 한다는게 아니면 그냥 놔두면 된다.
import json

# 같은 폴더 레벨에 있는 tag.json을 읽기 모드로 가져오고, 그것을 f라 지칭
with open('tag.json', 'r') as f:
    # tag_list에 현재 json 형식으로 불러온 f를 저장
    tag_list = json.load(f)
    
new_list = []
for tag in tag_list:
    # 우리의 목적에 나와있는 것과 같이 모델의 이름을 설정해주는 것이다. 
    # 지금 작업하고 있는 tag 데이터는 movies에 만든 Tag 모델에 들어가는데, 
    # 그 모델의 이름을 우리는 'tag'로 쓰기로 함!
    new_data = {"model": "movies.tag"}
    new_data["fields"] = {}
    new_data["fields"]["name"] = tag
    new_list.append(new_data)

# json 파일을 만들기 전에 생성된 모델의 형태 확인    
print(new_list) 

# json 파일로 생성 ㄱㄱ
# 아까와 같이 tag_data.json이라는 파일을 쓰기모드로 가져오고 인코딩 형식을 지정해줌
# 우리는 tag_data.json이라는 파일이 없는데, 이렇게 쓰면 자기가 알아서 파일을 만들어줌!
with open('tag_data.json', 'w', encoding='UTF-8') as t:
    json.dump(new_list, t, ensure_ascii=False, indent=2)
  • 파일이 생성되었는지 확인한다.
  • 이제 해당 내용을 db에 실어보도록 하겠다.
    • fields 오타 조심^^
    • 오타가 있으면 에러메세지가 한 페이지가 나온다 ㅎ
    • 아래와 같은 메세지가 나오면 성공이다.
$ python manage.py loaddata tag_data.json

  • 이제 db로 가서 잘 실렸는지 확인한다.


- movie 데이터

  • 이제 csv 파일을 json으로 변경하는 작업을 할 것이다. 물론 json 형식으로 본인이 직접 짜도 좋다. 하지만 나는 8000개 가량의 데이터가 있었고 내 눈을 버리고 싶지 않았다. 그래서 아래의 사이트로 가서 변경을 시도했다.
    CSV to JSON
  • 다음과 같이 파일을 업로드하고 convert를 눌러 변환을 진행하면 된다.
  • 그리고 파일을 저장한 후, 내 프로젝트 폴더에 넣으면 된다. 그러면 아래와 같이 vs code에서 확인할 수 있다. 형식을 보니 아주 이쁘게 잘 들어온 것을 볼 수 있다.
  • 하지만 한계가 있다. tag 부분이 json 형식으로 올라오지 않았다.
  • 저 부분까지 포용해서 json 형식으로 변환해자.
    movies_loader.py
    • stripreplace를 한 번에 다 쓴거는 처음이다. 그래도 이렇게 해서 두 함수를 한 번에 쓰는게 별로 좋아보이지는 않지만, 같이 쓸 수는 있다는 것을 알게 되었고, json 형식으로 머리를 좀만 굴려서 바꿀 수 있다는 경험을 얻게 되었다.
import json

tag_list = ["Adventure", "Fantasy", "Animation", "Drama", "Horror", "Action", "Comedy", "History", "Western", "Thriller", "Crime", "Documentary", "ScienceFiction", "Mystery", "Music", "Romance", "Family", "War", "TVMovie"]

with open('movies.json', 'r') as f:
    movies = json.load(f)
    
new_list = []
for movie in movies:
    new_data = {"model": "movies.movie"}
    # tag 값이 없는 경우도 있기 때문에 있는지 없는지 확인
    # 만약 json 파일이 완전 깔끔하다면 해당 과정 필요없음! (이때는 tag때처럼만 해도 됨)
    if movie['tag']:
        # []를 없애기 위해 strip을 해주었고, 그 다음으로 띄어쓰기를 없애기 위해 replace를 해주었다.
        # 그리고 ,를 기준으로 나눠주었다. 
        tags = movie['tag'].strip('[]').replace(' ', '').split(',')
        # tag와 movie를 이어줄 때 이름값이 아닌 pk 값으로 이어주어야 하기 때문에 해당 리스트 생성
        tag_int_list = []
        for tag in tags:
            # index는 0부터 시작하고, pk는 1부터 시작하기 때문에 이것을 맞춰주기 위한 조치
            tag_int = tag_list.index(tag) + 1
            tag_int_list.append(tag_int)
        movie['tag'] = tag_int_list
    else:
        movie['tag'] = []
    new_data['fields'] = movie
    new_list.append(new_data)
    
with open('movies_data.json', 'w', encoding='UTF-8') as m:
    json.dump(new_list, m, ensure_ascii=False, indent=2)
  • 위 작업을 통해 다음과 같이 파일을 생성할 수 있었다. 그리고 바로 db에 내용을 얹어보도록 한다.
$ python manage.py loaddata movies_data.json

  • 내용이 성공적으로 반영된 것을 볼 수 있다. 여기서 아니 왜 얘는 pk도 있는데 movieId가 또 있는거야라고 할 수 있다. 내가 모자라서 그런거는 아니고 머신러닝 필터링을 돌리려면 필요해서 만들어 놓은 값이고 지우기 귀찮아서 그냥 그대로 사용해서 그런 것이다.

😭 dumpdata로 fixture.json 만들기

- dumptdata 진행하기

  • 현재 나는 django의 모든 db들을 다 보유하고 있다. 그러므로 그냥 단순하게 dumpdata 명령어를 입력하면 안 된다. 어떤 것을 뺄 것인지 이름을 잘 작성해 주어야 한다.
$ python manage.py dumpdata movies > movies/fixtures.json 
  • 이렇게 하면 아래와 같은 폴더 구조가 나오게 된다.
  • 이제 사진과 코드를 보면서 의미를 해석해보자.
    • movies에 속해 있는 db를 dumpdata를 통해 빼오겠다는 뜻이다. 여기서 movies라는 app의 이름이 없다면 다 빼오겠죠? ㅎ
    • 그리고 경로와 파일 명을 설정해 주었다. 나는 movies 라는 폴더 안에 fixtures.json이라는 이름으로 빼온 데이터 값을 저장한 것이다.
  • movies/fixtures.json 구조
    • 양이 많아 다 보여주지는 못하지만 빨간색이 tag, 파란색이 movie 데이터이다.

- fixtures.json으로 db에 내용 붙이기

  • 깃헙에서 만약 db가 없는 상태로 코드를 받고 db를 채워야 한다면, 처음과 같이 db를 migrate해주고, 아래의 코드를 통해 내용을 넣을 수 있다.
$ python manage.py loaddata movies/fixtures.json 
profile
https://github.com/nikevapormax

0개의 댓글