pythonanywhere에서 DB 마이그레이션(migration) 하기

Computer 관심/Flask|2021. 10. 9. 23:34
반응형

https://flask-migrate.readthedocs.io/

 

 

로컬 마이그레이션 

set FLASK_APP=main.py

 

1. 마이그레이션 폴더를 추가함

flask db init

2.  마이그레이션 파일 생성

(생성된 파일을 잘 봐야 한다고 함. 왜냐면 테이블 이름이나 칼럼 이름을 바꿀경우 수동으로 수정 필요)

$ flask db migrate -m "Initial migration."

3. 마이그레이션 적용

$ flask db upgrade

 

깃 커밋

1. 깃 커밋 후 푸쉬

 

파이썬 애니웨어에 적용

1. 파이썬 애니웨어에서 git pull (이를통해 적용을 시킬 파일까지 불러 올 수 있다.)

2. 파이선 애니웨어에서도 마이그레이션 적용

$ flask db upgrade

로컬에서 db를 수정한뒤 flask db upgrade명령어를 적어서 pythonanywhere에 적용한 모습

※ 호스팅한 서버의 마이그레이션 파일과 개발서버의 마이그레이션 파일이 같으면 문제가 날 가능성이 적을 겉이다.

 

 

이렇게 마이그레이션이 작동이 안되는 경우 해결법 

해결법 1. 마이그레이션 관련 파일 삭제 후 초기화

 

로컬

1. 다운그레이드로 디비를 되돌림

 

2. migration 폴더를 삭제 +  alembic_version 테이블을 제거

3. 마이그레이션 폴더를 추가함

flask db init

4.  마이그레이션 파일 생성

(생성된 파일을 잘 봐야 한다고 함. 왜냐면 테이블 이름이나 칼럼 이름을 바꿀경우 수동으로 수정 필요)

$ flask db migrate -m "Initial migration."

5. 마이그레이션 적용

$ flask db upgrade

 

6. git push

 

적용서버

1. alembic_version테이블 제거

2. 깃 풀로 새로 만들어진 마이그레이션 파일을 다시 받아옴

3. 마이그레이션 파일 적용

export FLASK_APP=main.py

 

$ flask db upgrade

 

 

 

해결법 2.

서버와 같게 만들어줌 - python anywhere에서 bash가 아닌 mysql을 클릭

 

1. alembic_version을 업그레이드 이전 버전으로 맞춤. 

 

2. 만약 alembic_version테이블 자체가 없으면 sql 쿼리를 통해 테이블 생성을 함

 

 

-- 테이블 만들기

CREATE TABLE alembic_version (
    version_num varchar(32) NOT NULL PRIMARY KEY
);

 

-- 테이블에 데이타 변경하기

UPDATE alembic_version SET version_num = '52220a6a6d76' WHERE version_num = 'c2d3b91fd96e';

 

-- 마이그레이션에 엉뚱한 쿼리가 있으면 변경해 줌

 

$ flask db upgrade

 

 

해결법 3. 마이그레이션을 안쓰는법

sql문을 써서 직접 실제 서버의 테이블을 업데이트를 한뒤 ( ALTER TABLE 아래 링크는 sql로 수정하는 법)

https://stackoverflow.com/questions/92082/add-a-column-with-a-default-value-to-an-existing-table-in-sql-server

※ 유용한 쿼리 show tables;, describe <table name>;

 

그냥 git으로 파일을 push 한뒤 sql로 테이블 구조를 바꾸고 alembic_version 테이블에 값을 로컬에 있는 것과 똑같이 만들어줌

 

 

UPDATE alembic_version SET version_num = '52220a6a6d76' WHERE version_num = 'c2d3b91fd96e';

 

 

 

- nullable= false 인 필드를 추가 시켜야 하는 경우

https://medium.com/the-andela-way/alembic-how-to-add-a-non-nullable-field-to-a-populated-table-998554003134

 

Alembic: How to Add a Non-Nullable Field to a Populated Table

It is quite easy to add a non-nullable field to an empty table. Any migration tool, including Alembic, can automatically generate a…

medium.com

간단하게 말하자면 이건 자동이 아니다. ㅠㅠ 직접 마이그레이션 파일을 수정하는 것이다.

nullable = false로 바로 했을 경우 기존에 있던 row들에 값이 없기 때문에 

먼저 nullable = true로 만들어준 뒤 기존 필드에 값을 넣고 그걸 nullable =false로 바꾸어주는 방법이다.

 

 

-nullable = false면서 unique면...

nullable을 true로 바꾸고 기존에 값에 unique한 값 (row의 index나 uid) 을 넣어준 뒤

nullable을 false로 바꾸면 될 것이다. 

 

 

-메이저 체인지는 인식하는데(삭제, 생성) 값의 크기가 변경됬을때 작동 안하면

 

compare_type = True 추가해줘야함 (어디에 추가하는지 중요) 링크 참조

https://stackoverflow.com/questions/58532518/why-flask-migrations-does-not-detect-a-fields-length-change

 

 

- 만약 개발서버에서는 sqlite를 쓰고 실서버를 mysql을 쓰는 경우 엄청 고생하게 됨.

 

 

 

 

 

댓글()

2) 플라스크 api pythonanywhere MYSQL DB와 연결하기

Computer 관심/Flask|2021. 9. 23. 15:16
반응형

이전글에서 말했듯 그냥 SQLite 를 디비서버 대신 사용하려 했었다.

sqlite 파일이 파일루트에 생성된 것도 볼 수 있었는데

문제는 쓰기에서 파일의 변형으로 보아서인지 쓰기 동안 읽기도 불가능 한줄알았다.

(알고 보니 그게 문제는 아니였다.)

 

 

MYSQL DB로 옮겨보려고 한다.

 

 

* sqlite에서 mysql로 옮기면서 디비를 만들때 디비설정에서 여러에러 발생한다.

1) sqlite에서 string에 size를 정해줄 필요가 없었는데 mysql에서는 정해 줘야한다.

2) default에 false 대신 0를 넣어줌

3) server_default에서는 스트링만 받는다. 

4) 데이터 입력시 엑셀에 빈칸은 nan으로 되어 pandas

(nan can not be used with MySQL 에러가 발생)

5. foreign key 참조 값은 string인데 그거를 받는 필드값을 int로 설정한경우 (sqlite에서는 됬었다...)

 

등, MySQL을 설치하기 귀찮다고 로컬에서 안깔고 하니 더 고생이다.

 

이렇게 에러가 발생해서 클라이언트와 연결이 안되면 cors 에러를 보내기 때문에 엉뚱한데서 에러를 찾으려다 시간을 보낼 수가 있다.

 

 

 

일단 파이썬애니웨어에서 MySQL 디비를 만든다.

 

비밀번호를 잊어버리지 않으려고 엄청 쉽게 만들었더니 아래와 같이 나온다.

 

 

아래의 화면은 생성된 디비의 정보이다.

start a console on 저 링크를 클릭하면 콘솔로 들어가져서 여러가지 쿼리를 입력 할 수 있다.

 

 

 

SQL디비로 연결하는 기존의 코드는 이와 같다.

app = Flask(__name__)
CORS(app)
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///inventory.db"
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True

bash 화면에서 pymysql을 설치하고 

pip install pymysql

import를 할 필요는 없다.

 

이러한 형식을 바꾸어줄것이다.

app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://username:password@localhost/db_name'
# flask sqlalchemy를 쓸 경우 추가. https://www.pythonanywhere.com/forums/topic/11116/
# 안쓰니 서버가 멈쳐버림
app.config['SQLALCHEMY_ENGINE_OPTIONS'] = {'pool_recycle' : 280}

 

 

이런식으로 들어가게 될 것이다. 

 

app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://seansoft:bbc123456@seansoft.mysql.pythonanywhere-services.com/seansoft$default'

 

깃이나 파일을 직접 올린뒤 WEB 메뉴에서 리로드를 한다.

 

bash console에 들어가 show tables를 치니 테이블들이 생성됨을 볼 수 있다.

 

row가 잘 생성됬는지 보기 위해선 

select count(*) from 테이블이름

 

 

자료 

플라스크 sqlalchemy 연결

https://stackoverflow.com/questions/27766794/switching-from-sqlite-to-mysql-with-flask-sqlalchemy

 

 

댓글()