가오리의 코딩일기

Ep03. 블로그 웹 애플리케이션 개발 본문

Python/flask

Ep03. 블로그 웹 애플리케이션 개발

류경혜 2022. 7. 15. 21:30

✏️ 터미널에 가상환경 연결하기

더보기

→ PyCharm이 아닌 VSC 사용중

→ blog/__init__.py 생성

→ python3 -m venv venv (가상환경 생성)

→ command+shift+p (파이썬 인터프리터 설정)

→ 터미널 시작? 부분에 (venv)가 없다면 control+shift+~ (새 터미널)

 

 

 

💡ORM 사용 예정 → Flask-SQLAlchemy, Flask-Login 설치

✏️ ORM: Object-Relational Mapping

→ 데이터베이스에 데이터를 저장하는 테이블을 파이썬 클래스로 만들어 관리하는 기술로 이해해도 좋다

→ 객체 지향적 코드로 인해 더 직관적이고 비즈니스 로직에 집중할 수 있도록 도와준다

→ 재사용 및 유지보수의 편리성이 증가하고 DBMS에 대한 종속성이 줄어든다

→ 완벽한 ORM만으로 구현하기가 어렵고 프로시저가 많은 시스템에서는 ORM의 객체지향적인 장점을 활용하기 어렵다

→ 프로시저 : 특정 작업을 위한 프로그램의 일부, 함수와 같은 의미

 

 

 

💻 pip insall Flask-SQLAlchemy

→ 파이썬을 위한 ORM 중 하나

→ Flask에서 사용하기 쉽게 만들어진 Flask-SQLAlchemy

 

 

 

💻 pip install Flask-Login

→ Flask 프레임워크를 위한 사용자 세션 관리 기능을 제공한다

→ 로그인과 로그아웃과 같은 일반적인 기능과 사용자 세션 시간을 연장해서 기억할 수 있는 기능들을 제공한다

→ 데이터베이스 등으로부터 유저 정보를 로딩하는 기능이나 로그인과 로그아웃을 넘어서는 권한 처리는 제공하지 않는다

 

 

 

 

💡 __init__.py로 애플리케이션 팩토리 만들기

✏️ __init__.py

→ 해당 디렉터리가 패키지의 일부임을 알려주는 역할

→ game, sound, graphic 등 패키지에 포함된 디렉터리에 __init__.py 파일이 없다면 패키지로 인식하지 않는다

     (python3.3버전부터는 init.py 파일이 없어도 패키지로 인식)

→ 하위 버전 호환을 위해 __init__.py 파일을 생성하는 것이 안전한 방법이다

더보기
# blog/__init__.py
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from os import path
from flask_login import LoginManager

def create_app():
    app = Flask(__name__) # Flask app 만들기
    app.config['SECRET_KEY'] = "IFP"

    @app.route("/")
    def home():
        return "home"
    @app.route("/about_me/")
    def about_me():
        return "introduce about myself ..."
    return app
# app.py
from blog import create_app

if __name__ == "__main__":
    app = create_app()
    app.run(debug=True)

 

 

 

 

💡 추가적 실습

더보기
# blog/__init__.py
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from os import path
from flask_login import LoginManager

def create_app():
    app = Flask(__name__) # Flask app 만들기
    app.config['SECRET_KEY'] = "IFP"

    @app.route("/")
    def home():
        return "home"

    @app.route("/about_me/")
    def about_me():
        return "introduce about myself ..."

    @app.route("/shop")
    def shop():
        return "shop"

    @app.route("/shop/products")
    def shop_products():
        return "shop_products"

    @app.route("/shop/login")
    def shop_login():
        return "shop_login"
    return app

 

 

 

✏️  BluePrint

→ 큰 application을 단순화시키는 역할을 하고 Flask extension 등록을 위한 중심 수단으로 쓰인다

 

 

💡auth.py& views.py

더보기
# blog/__init__.py
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from os import path
from flask_login import LoginManager

def create_app():
    app = Flask(__name__) # Flask app 만들기
    app.config['SECRET_KEY'] = "IFP"

    from .views import views
    app.register_blueprint(views, url_prefix="/blog")
    
    return app
# blog/views.py
from flask import Blueprint
views = Blueprint("views", __name__)
@views.route("/")
def blog_home():
    return "This is Blog home."

@views.route("/about_me")
def about_me():
    return "Introduce about myself..."

→ url_prefix=”/blog” : /blog에 /가 붙으면 views의 blog_home()이, /about_me가 붙으면 views의 about_me()가 수행된다

→ flask는 blueprint를 이용해서 url을 관리한다

 

 

 

 

💡 플라스크의 render_template()

더보기
# blog/auth.py
from flask import Blueprint, render_template

auth = Blueprint("auth", __name__)

@auth.route("/login")
def login():
    return "This is login page."

@auth.route("/logout")
def logout():
    return "This is logout page."

@auth.route("/sign-up")
def signup():
    return "sign up!"
# blog/views.py
from flask import Blueprint, render_template

views = Blueprint("views", __name__)

@views.route("/")
def blog_home():
    return render_template("home.html")

@views.route("/about_me")
def about_me():
    return "Introduce about myself..."
<!-- blog/templates/home.html -->
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Blog Home Page</title>
  </head>
  <body>
    <h1>Welcome!</h1>
    <p>This is blog home page...</p>
  </body>
</html>
더보기
# blog/views.py
from flask import Blueprint, render_template

views = Blueprint("views", __name__)

@views.route("/")
def blog_home():
    return render_template("home.html", blog_name="RYUKYUNG", message="hi")

@views.route("/about_me")
def about_me():
    return "Introduce about myself..."
<!-- blog/templates/home.html -->
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Blog Home Page</title>
  </head>
  <body>
    <h1>Welcome!</h1>
    <p>This is blog home page...</p>
    <p>blog name : {{blog_name}}</p>
    <p>message : {{message}}</p>
  </body>
</html>

→ render_template() : flask 아래의 templating.py 안에 정의되어 있다

→ 주석을 보면 template_name_or_list 와 context를 인자로 받는다

→ context가 화면에 잘 적용된다

→ 플라스크의 jinja 템플릿 엔진 덕분이다

→ {{}} 이렇게 중괄호가 있으면 jinja 템플릿 엔진은 변수로 인식

→ context로 값을 전달할 수 있다

 

 

 

💡 Boostrap 사용하기: flask가 정적 파일을 다루는 방법

https://startbootstrap.com/theme/clean-blog에서 템플릿 다운로드 받기

→ 위의 주소에서 다운받은 html 파일 4개를 templates에 넣어두고, views 파일 수정

 

 

 

✏️ 플라스크에서 정적파일 관리하는 방법

{{ url_for('static', filename='style.css')}}

→ 일부 CSS를 추가하여 구성한 HTML 레이아웃에 스타일을 추가할 수 있다

→ 스타일은 변경되지 않기 때문에 템플릿이 아닌 정적 파일이다

→ Flask static는 디렉토리에 상대적인 경로를 취하여 flaskr/static 제공하는 뷰를 자동으로 추가한다

더보기
# blog/views.py
from flask import Blueprint, render_template

views = Blueprint("views", __name__)

@views.route("/")
def blog_home():
    return render_template("index.html")

@views.route("/about_me")
def about_me():
    return render_template("about.html")

→ 모든 템플릿들은 base.html을 상속받아 만들어진다

→ 기본이 되는 부분들은 그대로 두고 변화하는 부분만 작성하자는 거

→ base.html에 정적파일을 처리하는 방법이 나와있음

→ static 폴더에 js, css, assets를 넣는다

→ <script src="{{ url_for('static', filename='js/scripts.js') }}"></script>

→ url_for을 활용해서 정적파일들을 불러온다

 

 

 

💡 jinja 템플릿 엔진의 상속

✏️ jinja 템플릿 엔진

→ 템플릿 : 응답 텍스트를 포함하고 있는 파일, 동적 파트에 대한 변수를 포함한다

→ {% ~~~~~ %} : 프로그래밍 영역

→ {{ ~~~~~~~ }} : 변수 출력 영역

→ {# ~~~~~~ #} : 주석 영역