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을 쓰는 경우 엄청 고생하게 됨.

 

 

 

 

 

댓글()

파이썬으로 Firestore 에 데이터 올리기

Computer 관심/Flask|2020. 11. 9. 22:54
반응형

플러터로 어플리케이션을 제작하였고, 어플리케이션에 필요한 데이터를 제공할 수 있는 서버가 필요했다.

파이어베이스의 파이어스토어는 쉽고 다양한 언어로 SDK를 제공한다. 그래서 플라스크를 사용하여 데이터를 올리는 간단한 서버를 만들었다. (굳이 서버로 만들지 않아도 됨....)

 

 

 

1. 웹사이트에서 서비스 어카운트 키 다운 받기

1) 파이어베이스에 들어가 새로운 프로젝트를 만든다.

2) 

 

 

3) service accounts 탭에 들어가면 아래와 같은 화면을 볼 수 있고

파이썬을 클릭한다.

4) Generate new private key 다운로드

 

5) 받은 json형식의 파일을 serviceAccountKey라고 이름을 변경한다.

 

6) 파이썬이 있는 폴더에 함께 놓는다.

 

 

2. firestore 만들기

1) 좌측 클라우드 파이어스토어를 클릭하면

서버를 선택할 수 있고 한국에서 빠른 실행을 할 수 있도록 south east2 를 선택했다.

 

2)

 

3. 파이썬 코드

firebase_admin과 Flask를 설치하고 아래와 같이 코드를 만든 뒤 실행하면

firestore에 대량으로 데이터를 업데이트 가능하다.

from flask import Flask,
import firebase_admin
from firebase_admin import credentials
from firebase_admin import firestore
import json

#서비스어카운트키 파일에 있는 json을 불러옴
cred = credentials.Certificate("./serviceAccountKey.json")
firebase_admin.initialize_app(cred)
firebase_db = firestore.client()

app = Flask(__name__)

# localhost:8000/add 로 들어갈시 작동
@app.route("/add", methods=['GET'])
def start():
	# firestore에 올릴 json 파일 불러드림
    with open('./stock_code.json', encoding='utf-8') as f:
        datas = json.load(f)
        
    # 아래는 테스트를 해보기 위한 데이터
    # datas = [{'name': '당근','code': '012345'},{'name': '오이','code': '012341'}]
    # print(datas)

    for data in datas:
    	# document() 라고 하면 자동으로 다큐먼트의 ID가 생성됨. 
        document = firebase_db.collection('콜렉션이름적기').document()
        document.set(data)
    return 'success'
    
# 공개아이피와 포트8000번 디버그 모드로 열기
if __name__ == '__main__':
    app.run(host='0.0.0.0',  port="8000", debug=True)

 

 

 

 

댓글()

플러터에서 firebase_auth와 flask 서버 같이 사용하기.

Computer 비관심/Flutter|2020. 11. 7. 00:33
반응형

이렇게 사용하면 아래와 같은 장점이 있을 것 같다.

1. 사용자 개인정보를 직접 저장하고 있지 않아도 된다.

 - 개인정보의 보안이나 관리가 어렵다. 

2. 서버에서 구현하기 귀찮은 모바일확인, 페이스북&구글로그인 등을 쉽게 구현 가능하다.

3. firestore의 단점인 과금 문제를 보완 가능. - 정말 필요한 채팅서비스에서만 firestore를 사용하면 될듯. 나머지는 flask SQL서버에 저장.

4. 파이썬을 서버로 사용하기 때문에 데이터처리에도 유용하지 않을까.....?

 

플러터에서 

1. firebaseAuth로 로그인을 함

2. firebaseAuth로 아이디 토큰을 받음

3. http post로 토큰을 서버로 보냄.

 

서버에서

1. post로 온 토큰을 firebase의 

    decoded_token = auth.verify_id_token(id_token)

    uid = decoded_token['uid'] 사용해서 유저를 확인한다.

 

 

로컬호스트에서 진행 했기 때문에 실제 서비스를 하면

어떤 문제가 생기는지는 모르겠다. 

모바일 기기에서 http post를 보낼때 localhost라고 적으면 모바일이 ip를 알지 못하니

ipconfig에 들어가서 실제 로컬호스트 아이디를 입력해줘야 한다.

 

 

댓글()

플라스크 사용해보기

Computer 관심/Flask|2018. 5. 3. 15:11
반응형

장고를 가지고 심심풀이로 API서버를 만들어 보려고 하니까

장고를 놓은지 오래되서 기억이 가물 가물 했다. 또.... 이전에 일했던 기억 때문에 쓰고 싶지 않았다.. ㅠㅠ

확실히 장고가 좋긴하지만 심플한 서버만 사용하고 싶어서 플라스크로 만들어 보면 어떨가 생각이 들었다.

 

 

 

1. 플라스크 시작하기

 

플라스크 홈페이지(http://flask.pocoo.org/)를 들어가면 아래와 같이 정말 간단하게 플라스크 서버를 만든 것을 볼 수 있다.

 

1) main.py 파일 작성

from flask import Flask
app = Flask(__name__)

@app.route("/")
def getHelloMsg():
    return "Hello World!"

 

2) command로 서버 실행하기 

$ pip install Flask
$ FLASK_APP=main.py flask run
 * Running on http://localhost:5000/

윈도우 실행시 FLASK_APP=main.py이 아닌 set FLASK_APP=main.py라고 적어야 한다.

장고서버와 비교했을 때 단 하나의 파이썬 파일 하나로 심플하게 서버를 만들 수 있다.

 

 

서버에 아무런 설정 없이 이대로 브라우저에서 요청을 할 시 브라우저는 아래와 같은 에러가 발생한다.

(브라우저가 아닌 서버를 통해 데이타를 요청하면 줌)

Failed to load http://localhost:5000/: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8080' is therefore not allowed access.

 

 

 

2. 크로스오리진 문제 해결하기

 

서버에서 브라우저의 크로스브라우징을 허용을 해줘야한다. 그래야 데이타를 클라이언트에서 리턴 받을 수 있다. 여기서 사용한 모듈은 flask-cors다

 

flask-cors 홈페이지

http://flask-cors.readthedocs.io/en/latest/

 

1) 설치

$ pip install -U flask-cors

 

2) 코드에 적용

from flask import Flask
from flask_cors import CORS

app = Flask(__name__)
CORS(app)

@app.route("/")
def getHelloMessage():
  return "Hello"

이렇게 하면 더 이상 브라우저에서 에러가 발생하지 않는다. 세부적으로 설정하는 것은 홈페이지를 확인하자

 

데이터를 받고 싶으면 아래와 같이 사용한다.

@app.route("/", methods = ['POST']) 
def getHelloMsg():
  # url 요청을 통해 받은 데이터
  search = request.args.get("search")
  page = request.args.get("page")


  # 폼을 통해 입력받은 데이터
  email = request.form.get('email')
  password = request.form.get('password')


  #json 요청을 통해 받은 데이터
  data = request.get_json()
  
  return "hello"

여기까지 하게 되면 클라이언트는 사용자의 데이터를 입력받고 서버의 내용을 출력해주는 기능만 하고 데이터의 가공은 서버에서만 하도록 테스크의 분리가 가능하다. 

 

 

 

3. flask-SQLAlchemy를 사용하여 데이터 저장하기

 

flask-SQLALchemy는 sql문을 작성하는 대신에 ORM으로 디비를 쉽게 관리 할 수 있도록 도와주는 모듈이다.

http://flask-sqlalchemy.pocoo.org/2.3/quickstart/

 

1) 플라스크 알케미 설치하기

pip install flask-sqlalchemy

 

2) SQLAlchemy를 세팅하고 DB의 모델(구조)까지 만들기

 

아래의 코드는 flask-SQLAlchemy와 사용하기 간단한 sqlite db를 사용한 공식 예제이다.

 

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/test.db'
db = SQLAlchemy(app)


class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80), unique=True, nullable=False)
    email = db.Column(db.String(120), unique=True, nullable=False)

    def __repr__(self):
        return '<User %r>' % self.username

 

3) 만들은 모델을 바탕으로 디비 생성하기

- cmd창에 python이라고 쳐서 파이썬 쉘로 들어간다.

- 아래와 같이 입력한다.

>>> from yourapplication import db 
>>> db.create_all()

 

4) 모델을 바탕으로 객체를 만들기

>>> from yourapplication import User
>>> admin = User(username='admin', email='admin@example.com')
>>> guest = User(username='guest', email='guest@example.com')

 

5) 객체를 디비에 저장하기

>>> db.session.add(admin)
>>> db.session.add(guest)
>>> db.session.commit()

 

6) 데이터에 저장된 값 불러오기

>>> User.query.all()
[<User u'admin'>, <User u'guest'>]
>>> User.query.filter_by(username='admin').first()
<User u'admin'>

그러나!!!!!!

 

 

 

4. flask-migrate를 통해 디비구조를 변경하기

 

 

이때 테이블의 구조를 수정해야 할 때 지금까지 만든 디비를 날리고 다시 만들어야 한다는 단점이 있다.

이렇게 할 필요없이 디비변경을 관리해 주는 것이 migration이라고 하는데 장고처럼시퀄알케미에서는 기본으로 제공을 하지 않았다.

이럴바엔 그냥 sql문을 작성하고 수정도 sql문으로 하는게 더 낫겠다 라고 생각이 들었다.

 

그리고 그냥 시퀄알케미를 지우고 sql문으로 디비를 직접 만들려고 하는 찰나.

flask-migrate라는 모듈이 있는 것을 알게 됬고 이걸 사용함으로써 디비구조변경을 더 간단히 할 수 있게 되었다.

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

 

여기 나온데로 따라하면 간단하게 마이그레이션을 할 수 있다

 

 

 

추가사항!

실행하기전에 set FLASK_DEBUG=True를 커멘드에 입력을 하면 에디터에 코드가 변경될 때마다. 자동으로 리로드가 된다.

댓글()