지난글
https://ilsancityboy.tistory.com/72
지난 번에 이어 이번글에서는 총 2가지를 할 것이다.
1.회원가입 페이지 만들기
2.sql (데이터베이스 연동하기)
1. register html
<!-- templates/main_page.html -->
{% extends 'layout.html' %}
{% block title %}회원 가입{% endblock %}
{% block content %}
<div class="text_wrapper">
<div class="top">
<h1>회원 가입</h1>
</div>
<hr>
<div class="middle">
<form method="POST" action="/register">
<h1>아이디</h1>
<input type="text" placeholder="아이디" id="username" name="username" required>
<h1>비밀번호</h1>
<input type="password" placeholder="비밀번호" id="password" name="password" required>
<h1>이메일</h1>
<input type="email" placeholder="이메일" id="email" name="email" required>
<button type="submit" class="custom_button">회원가입</button>
</form>
</div>
<hr>
<div class="register_bottom">
<a href="{{ url_for('login') }}">
<p>이미 계정이 있으신가요?</p>
<button class="custom_button">로그인하기</button>
</a>
</div>
</div>
{% endblock %}
먼저 지난 번에 미리 만들어둔 layout.html을 똑같이 불러오고 간단하게 회원가입에 필요한 입력 폼들만 만들어주면 된다.
2. sql 연동하기
2-1. 라이브러리 설치
pip install flask-sqlalchemy Werkzeug
Flask-SQLAlchemy: SQLAlchemy ORM을 Flask와 통합하여 데이터베이스를 다루는 데 사용된다.
즉, Flask 애플리케이션에서 데이터베이스의 테이블을 Python 클래스로 정의하고, 이를 사용하여 데이터베이스를 쉽게 생성하고 쿼리할 수 있도록 해준다. 이를 통해 개발자는 SQL 쿼리를 직접 작성하지 않고도 Python 객체를 통해 데이터베이스와 상호작용할 수 있다.
Werkzeug: 보안과 관련된 여러 기능을 제공하는 유틸리티 라이브러리이다.
2-2. 애플리케이션 설정
1편 글에서 작성했던 app.py 코드를 다시 보면
from flask import Flask, render_template, request, redirect, url_for
app = Flask(__name__)
여기서 코드를 추가해 기본설정을 맞춰주었다.
from flask import Flask, render_template, request, redirect, url_for , flash
from flask_sqlalchemy import SQLAlchemy
from werkzeug.security import generate_password_hash, check_password_hash
app = Flask(__name__)
app.config['SECRET_KEY'] = '1234'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///users.db'
db = SQLAlchemy(app)
먼저 추가된 부분을 보자면
1. flash
메시지 플래싱을 제공하는 함수이다. 쉽게 말해 사용자에게 알림이나 경고 메시지를 줄때 사용된다.
#flash 함수에 대해 설명 추가글 올릴 예정
2. from flask_sqlalchemy import SQLAlchemy
위에 설명한 것처럼 Flask와 SQLAlchemy를 통합하여 Flask 애플리케이션에서 데이터베이스를 쉽게 다룰 수 있도록 도와주는 모듈을 가져온 것
3.from werkzeug.security import generate_password_hash, check_password_hash
해시값을 설정하고 일치하는지 확인하는 도구를 가져온 것.
4.app.config['SECRET_KEY'] = '1234'
애플리케이션의 시크릿 키를 설정합니다. 시크릿 키는 보안 관련 기능에 사용한것
5.app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///users.db'
SQLAlchemy 라이브러리를 사용하여 데이터베이스와 연결할 때 필요한
URI(Uniform Resource Identifier)를 설정하는 부분
sqlite://: SQLAlchemy에서 SQLite 데이터베이스를 사용할 것임을 나타냄
/users.db : SQLite 데이터베이스 파일의 경로입니다. users.db라는 파일이 현재 작업 디렉토리에 생성될 것
2-3. 데이터베이스 모델 정의
class User(db.Model):
id = db.Column(db.Integer, primary_key=True) # 사용자 ID, 자동 증가
username = db.Column(db.String(150), nullable=False, unique=True) # 사용자 이름, 고유값
password = db.Column(db.String(150), nullable=False) # 사용자 비밀번호
email = db.Column(db.String(150), nullable=False, unique=True) # 사용자 이메일, 고유값
sql에서 어떤식으로 데이터가 저장되는지 모델을 정의하는 부분이다.
db.Integer: 정수 형식의 데이터 타입이란 뜻.
nullable = False 는 이 부분은 비워져있으면 안된다는 뜻.
unique = True 는 각각 고유의 username 즉, 중복되는것이 없어야 한단 뜻.
즉 user라는 테이블에는
id | username | password | |
1 | user | user1234 | test@gmail.com |
2 | admin | admin1234 | hi@daum.net |
3 | guest | guest1234 | ggyo@naver.com |
이런식으로 저장이 되는 것
2-4. 데이터베이스 생성
@app.before_request
def create_tables():
app.before_request_funcs[None].remove(create_tables)
db.create_all()
Flask 애플리케이션이 요청을 처리하기 전에 실행되는 함수를 정의하는 부분이다.
각 요청이 처리되기 전에 실행되는 Flask의 before_request 데코레이터를 사용하여 create_tables 함수를 등록하고 있다.
즉, 맨 처음에 실행하게 되면 데이터베이스가 없을 시 데이터베이스 파일을 만드는 작업인 것.
3. 회원가입 라우트 구현
@app.route('/register', methods=['GET', 'POST'])
def register():
if request.method == 'POST': # 사용자가 회원가입 양식을 제출했을 때
username = request.form['username']
password = request.form['password']
email = request.form['email']
hashed_password = generate_password_hash(password, method='pbkdf2:sha256') # 비밀번호 해싱
new_user = User(username=username, password=hashed_password, email=email)
try:
db.session.add(new_user) # 새로운 사용자 추가
db.session.commit() # 데이터베이스에 커밋
flash('회원가입이 완료되었습니다!', 'success')
return redirect(url_for('login'))
except:
flash('회원가입 중 오류가 발생했습니다.', 'danger')
return redirect(url_for('register'))
return render_template('register.html') # 회원가입 양식 페이지 렌더링
hashed_password = generate_password_hash(password, method='pbkdf2:sha256')
입력된 password를 PBKDF2 알고리즘과 SHA-256 해시 함수를 사용하여 안전하게 해싱한 값을 반환한다.
즉, 가입을 하게되면 데이터베이스에는 평문의 비밀번호가 아닌 비밀번호 해싱값이 저장되게 되며 앞으로 로그인 할 때마다 입력한 비밀번호를 해싱 처리하여 데이터베이스 안에 있는 해싱값과 일치한지 확인하고 로그인 처리를 하게 될 것.
(보안차 넣은 부분)
flash('회원가입이 완료되었습니다!', 'success')
flash는 사용자에게 알림을 띄우는 것.
단순히 이 코드로 알람이 뜨는것이 아닌 html에 별도 설정을 해줘야 한다.
{% with message = get_flashed_messages() %}
{% if messages %}
<script>
alert("{{messages[-1]}}")
</script>
{% endif %}
{% endwith %}
이 코드를 html에 넣어 app.py에서 flash된 값을
get_flashed_messages() 로 html에서 가져와 alert를 띄워주는 것
4. html 수정
따라서 맨처음에 만든 register.html 에 flash 를 위한 코드를 넣어주자.
<!-- templates/main_page.html -->
{% extends 'layout.html' %}
{% block title %}회원 가입{% endblock %}
{% with message = get_flashed_messages() %}
{% if messages %}
<script>
alert("{{messages[-1]}}")
</script>
{% endif %}
{% endwith %}
{% block content %}
<div class="text_wrapper">
<div class="top">
<h1>회원 가입</h1>
</div>
<hr>
<div class="middle">
<form method="POST" action="/register">
<h1>아이디</h1>
<input type="text" placeholder="아이디" id="username" name="username" required>
<h1>비밀번호</h1>
<input type="password" placeholder="비밀번호" id="password" name="password" required>
<h1>이메일</h1>
<input type="email" placeholder="이메일" id="email" name="email" required>
<button type="submit" class="custom_button">회원가입</button>
</form>
</div>
<hr>
<div class="register_bottom">
<a href="{{ url_for('login') }}">
<p>이미 계정이 있으신가요?</p>
<button class="custom_button">로그인하기</button>
</a>
</div>
</div>
{% endblock %}
결과물
app.py 전체코드
from flask import Flask, render_template, request, redirect, url_for , flash
from flask_sqlalchemy import SQLAlchemy
from werkzeug.security import generate_password_hash, check_password_hash
app = Flask(__name__)
app.config['SECRET_KEY'] = '1234'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////Users/user/Desktop/바탕화면/공부/파이썬/혼자 프로젝트/lol_clone/instance/users.db'
db = SQLAlchemy(app)
class User(db.Model):
id = db.Column(db.Integer, primary_key=True) # 사용자 ID, 자동 증가
username = db.Column(db.String(150), nullable=False, unique=True) # 사용자 이름, 고유값
password = db.Column(db.String(150), nullable=False) # 사용자 비밀번호
email = db.Column(db.String(150), nullable=False, unique=True) # 사용자 이메일, 고유값
@app.before_request
def create_tables():
# The following line will remove this handler, making it
# only run on the first request
app.before_request_funcs[None].remove(create_tables)
db.create_all()
@app.route('/')
def index():
return render_template('index.html')
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
username = request.form['username']
password = request.form['password']
user = User.query.filter_by(username=username).first()
if user and check_password_hash(user.password, password):
return redirect(url_for('index'))
else:
return render_template('login.html', error=True)
return render_template('login.html')
@app.route('/register', methods=['GET', 'POST'])
def register():
if request.method == 'POST': # 사용자가 회원가입 양식을 제출했을 때
username = request.form['username']
password = request.form['password']
email = request.form['email']
hashed_password = generate_password_hash(password, method='pbkdf2:sha256') # 비밀번호 해싱
new_user = User(username=username, password=hashed_password, email=email)
try:
db.session.add(new_user) # 새로운 사용자 추가
db.session.commit() # 데이터베이스에 커밋
flash('회원가입이 완료되었습니다!', 'success')
return redirect(url_for('login'))
except:
flash('회원가입 중 오류가 발생했습니다.', 'danger')
return redirect(url_for('register'))
return render_template('register.html') # 회원가입 양식 페이지 렌더링
if __name__ == '__main__':
app.run(debug=True)
다음 글에선 게시판 기능 추가에 대해 작성해보겠다.
'창작물' 카테고리의 다른 글
나만의 실습 사이트 만들기 (3편) (0) | 2024.06.20 |
---|---|
나만의 실습 사이트 만들기 (2.5편) (0) | 2024.06.18 |
나만의 실습 사이트 만들기 (1편) (0) | 2024.06.17 |
행맨 게임 (Hangman Game) 코드 창작 (1) | 2023.07.07 |
랜덤하게 로또번호를 만들어 출력시켜주는 코드 (0) | 2023.07.05 |