여기서는 조금 중요한 단계이다. db를 만들고 그 db안에 투두리스트를 쓴 다음에 get으로 불러오거나, post로 수정하거나 delete로 삭제할 것이기 때문이다.
1. sqlalchemy로 테이블 만들기
기존 코드에 이렇게 추가해준다.
from flask import Flask, render_template, url_for
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///test.db'
db = SQLAlchemy(app)
class Todo(db.Model):
id = db.Column(db.Integer, primary_key=True)
content = db.Column(db.String(200), nullable=False)
date_created = db.Column(db.DateTime, default=datetime.utcnow)
def __repr__(self):
return '<Task %r>' % self.id
@app.route('/')
def index():
return render_template('index.html')
if __name__ == "__main__":
app.run(debug=True)
나도 잘은 모르겠지만... 하나하나 간단히 짚고 넘어가자면
flask_sqlalchemy패키지에서 SQLALchemy라는 클래스(?)를 불러옴. datetime이라는 함수도 같이 쓸것이다.
자세히는 모르겠지만 SQLAlchemy를 사용하려면 저렇게 컨피규레이션을 해줘야하는 듯 하다.
마지막에 ///test.db를 통해 test라는 이름의 db를 만들고 실행문을 적는 것 같다.
그리고 이건 Todo라는 클래스를 만드는 것 같은데..
그냥 테이블을 만든다고 생각하자~~
각 테이블의 속성을 살펴보면
id는 integer(정수)이자 primary_key(기본키)이다. 하나밖에 없고 추가될 때마다 1씩 늘어나는.. 각 테이블의 데이트를 식별하기 위해 꼭 필요하다.
content는 200자 이내의 string(글자)이며 nullable=False는 공백을 허용안한다는 뜻 같다. 즉 필수적으로 써야한다는 것
date_created는 앞서 임포트해온 datetime함수를 통해 생성되는 입력 시간을 뜻한다. 디폴트로 datetime.utcnow로 되어있는데 db생성 당시의 컴퓨터의 시간을 UTC(협정세계시)형식으로 표현한 것 같다. (자세한 내용은 https://docs.microsoft.com/ko-kr/dotnet/api/system.datetime.utcnow?view=netframework-4.8 참고 바람)
마지막 __repr__(self) 함수를 통해 테이블에 있는 db를 리턴해주는 듯..
이해가 안되도 일단 그냥 넘어가야한다ㅎ
2. 파이썬 실행 후 db만들기
여기까지 썼으면 app.py를 잠시 종료한다.
그리고 env 가상환경으로 다시 들어가서(source 명령어 사용) 파이썬만 실행해준다.
- python3
- from app import db
이렇게 나오면 잘 되고 있는 것이므로 당황하지 않고 계속 진행한다.
- db.create_all()
여기까지 하면!!
test.db라는 파일이 만들어져있을 것이다.
이제부터 저 db안에 리스트가 만들어질 것이다..!
이제부터 진짜로 술술 할 수 있다.
다시 exit()를 타이핑하여 파이썬에서 나가주고..
3. index.html에 테이블 만들기, if/for구문 만들기
{% block body %}
<div class="content">
<h1 style="text-align: center">Task Master</h1>
{% if tasks|length < 1 %}
<h4 style="text-align: center">There are no tasks. Create one below!</h4>
{% else %}
<table>
<tr>
<th>Task</th>
<th>Added</th>
<th>Actions</th>
</tr>
{% for task in tasks %}
<tr>
<td>{{ task.content }}</td>
<td>{{ task.date_created.date() }}</td>
<td>
<a href="/delete/{{task.id}}">Delete</a>
<br>
<a href="/update/{{task.id}}">Update</a>
</td>
</tr>
{% endfor %}
</table>
{% endif %}
<div class="form">
<form action="/" method="POST">
<input type="text" name="content" id="content">
<input type="submit" value="Add Task">
</form>
</div>
</div>
{% endblock %}
index.html로 돌아와서 이렇게 코드를 만들어준다.
전체적인 구조를 보면
if절 안에 for문이 있는 형식이다. tasks는 이름을 임의로 쓴 것인데 app.py에서 이름으로 지정해줄 것이다.
- 플라스크로 if구문 만들기
{% if tasks | length < 1 %}
tasks에 db가 하나도 없을 때 보여줄 코드
{% else %}
그렇지 않은 경우의 코드
{% endif %}
if절 종료
- 플라스크로 for문 만들기
{% for task in tasks %}
for문 안에서 실행될 내용
(진자2 구문으로 데이터 가져오기)
{{ task.content }} 각 db의 content부분을 가져온다
{{ task.date_created.date() }} db가 추가되는 날짜를 입력한다
<a href="/delete/{{task.id}}">Delete</a>
<a href="/update/{{task.id}}">Update</a> task.id를 파라미터로 넘겨 app.py에서 받은 후 해당 데이터를 delete하거나 update해준다
{% endfor %}
만약 vue를 써봤다면.. 뷰 v-for문법이랑 매우 흡사함을 알 수 있다.
이렇게 했으면 app.py에서 각 메소드를 받아 데이터를 리턴해주는 구문을 작성해주자.
4. app.py에서 api 작성
일단 리퀘스트 모듈을 추가하여 api호출을 받을 준비를 해야한다.
다음과 같이 request, redirect 모듈을 추가
(1) post, get으로 불러오기
@app.route('/', methods=['POST', 'GET'])
def index():
if request.method == 'POST':
task_content = request.form['content']
new_task = Todo(content=task_content)
try:
db.session.add(new_task)
db.session.commit()
return redirect('/')
except:
return 'There was an issue adding your task'
else:
tasks = Todo.query.order_by(Todo.date_created).all()
return render_template('index.html', tasks=tasks)
try에는 실행할 코드이고
except에 예외처리를 해준다
(2) delete로 호출했을 때
@app.route('/delete/<int:id>')
def delete(id):
task_to_delete = Todo.query.get_or_404(id)
try:
db.session.delete(task_to_delete)
db.session.commit()
return redirect('/')
except:
return 'There was a problem deleting that task'
해당 아이디를 가진 db를 삭제해주는 함수
(3) update해줄 경우
@app.route('/update/<int:id>', methods=['GET', 'POST'])
def update(id):
task = Todo.query.get_or_404(id)
if request.method == 'POST':
task.content = request.form['content']
try:
db.session.commit()
return redirect('/')
except:
return 'There was an issue updating your task'
else:
return render_template('update.html', task=task)
기존 db에서 일치하는 id값을 찾아 덮어씌워준다.
이때 update.html을 리턴하는데 코드는 다음과 같다.
5. update.html 작성
\todoApp\templates\update.html
{% extends 'base.html' %}
{% block head %}
<title>Task Master</title>
{% endblock %}
{% block body %}
<div class="content">
<h1 style="text-align: center">Update Task</h1>
<div class="form">
<form action="/update/{{task.id}}" method="POST">
<input type="text" name="content" id="content" value="{{task.content}}">
<input type="submit" value="Update">
</form>
</div>
</div>
{% endblock %}
업데이트시에도 메소드는 포스트이다.
똑같이 base.html에서 상속받아 바디 부분만 고쳐준다.
6. 완성화면
이제 파이썬을 다시 실행하고 ctrl F5를 해주면
짠!! 첫번째 투두앱 완성!!!
추가를 해보자.
성공적으로 추가된 모습 !
또 추가해보자
수정도 해볼까
오... 성공적.. 삭제도 된다...
끝~~~
마지막엔 급하게 마무리했지만 자세한 코드는 원작자 깃허브에 나와있다.
https://github.com/jakerieger/FlaskIntroduction (여기에)
생각보다 쉬웠고 다음번에는 나 혼자 처음부터 끝까지 만들어봐야겠다.
그럼 다음 리뷰까지 ㅎㅇㅌ ㅎㅇㅌ
'왕초보를 위한 에러로그' 카테고리의 다른 글
파이썬 플라스크-sqlalchemy를 이용한 투두리스트 만들기(A-Z) (3)css, templates만들기 (0) | 2019.12.29 |
---|---|
파이썬 플라스크-sqlalchemy를 이용한 투두리스트 만들기(A-Z) (2)파이썬 파일 만들고 헬로월드 띄우기 (0) | 2019.12.29 |
파이썬 플라스크-sqlalchemy를 이용한 투두리스트 만들기(A-Z) (1)가상환경 만들기 (0) | 2019.12.29 |