WebFramework/[Flask]

우선 sqlalchemy 2.x에 버그가 있는 것 같음

AttributeError: 'Engine' object has no attribute 'execute'

pip install --force-reinstall 'sqlalchemy<2.0.0'

 


 

database = create_engine(app.config['DB_URL'], encoding = 'utf-8')

raise TypeError(
TypeError: Invalid argument(s) 'encoding' sent to create_engine(), using configuration MySQLDialect_mysqlconnector/QueuePool/Engine.  Please check that the keyword arguments are appropriate for this combination of components.

database = create_engine(app.config['DB_URL'], connect_args= {'encoding' : 'utf-8')

 

 

참고: https://docs.sqlalchemy.org/en/20/core/engines.html#custom-dbapi-args

 

 

 

'WebFramework > [Flask]' 카테고리의 다른 글

[Flask] Jinja2 사용법  (0) 2023.01.20
[Flask] Bootstrap 사용하기 (로그인)  (0) 2023.01.20
[Flask] 간단한 로그인 구현 (HTML, GET)  (0) 2023.01.20
[Flask] GET 사용법  (0) 2023.01.20
[Flask] httpi 설치  (0) 2023.01.20

[Flask] Jinja2 사용법

2023. 1. 20. 18:08

Jinja2 템플릿

웹페이지에 필요한 부분을 변경할 때 사용하는 문법

웹페이지에서 파이썬 프로그래밍 가능

 

jinja2_test.py

from flask import Flask, render_template

app = Flask(__name__)

@app.route('/hello/<id>')
def info(id):
    return render_template('jinja2.html', name=id)

if __name__ == '__main__':
    app.run(host='127.0.0.1', port='8080')

라우팅 경로로 받은 id 변수값을 인자로 받아서 jinja2.html을 리턴한다.

이 때, name이라는 변수 값에 넣어 jinja2.html에 적용시킨다는 의미이다.

jinja2.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <h1>Hello {{ name }}</h1>
  </body>
</html>

jinja2.html 파일 내에서 jinja2의 문법이 사용된다.

위 jinja2_test.py에서 name 변수에 값을 넣어 적용시킨다고 했다.

이 변수값을 사용하려면 

{ {  변수명 } }

위와 같은 문법으로 작성하면 된다.

 

결과

localhost:8080/hello 다음으로 Sso라는 값을 넘겼고 이를 받아 Hello Sso를 출력함을 볼 수 있다.

페이지 소스 코드를 확인해보면 {{name}}이 아닌 Sso가 들어갔다.

 

여러가지 변수를 사용하고 싶으면 

name = id와 같이 name1 = pwd, name2 = age와 같이 (원하는 변수명 = 값) 넘겨주고

{{name}}, {{name2}}, {{name2}}로 하면된다.


반복문

jinja2에서 반복문도 사용할 수 있다.

 

문법

{ % for i in items %}

{ { i } }

{ % endfor % }

 

사용해보자.

jinja2_test.py

from flask import Flask, render_template

app = Flask(__name__)

@app.route('/for')
def info():
    num_li = [1, 2, 3]
    return render_template('jinja2.html', nums=num_li)

if __name__ == '__main__':
    app.run(host='127.0.0.1', port='8080')

jinja2.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <ul>
      {% for i in nums %}
      <li>{{i}}</li>
      {% endfor %}
    </ul>
  </body>
</html>

결과

 

언뜻 보면 jinja2에서 사용하는 문법과 python의 문법이 비슷하다고 느껴진다.

하지만 차이점이 있다.

반복문의 문법을 더 살펴보자.

 

li = [1, 2, 3]

for i in range(len(li)):
    print(i)

 

위와 같은 파이썬 코드를 jinja2에서 써보자.

{ % for i in range(li | length) % }
{ { li[i] } } { { loop.index } }
{ % endfor % }

한 줄씩 보자.

  • range(len(li)) → range(li | length)
    • li의 길이만큼 반복
  • li[i] 
    • li의 인덱스(i)번 째 가져오기
    • 0부터 시작
  • loop.index
    • 반복문 횟수 가져오기
    • 1부터 시작

 

코드로 보자.

jinja2_test.py는 for문을 사용했던 파일과 같다.

jinja2.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <ul>
      {% for i in range(nums | length) %}
      <li>{{loop.index}} 번 num : {{nums[i]}}</li>
      {% endfor %}
    </ul>
  </body>
</html>


조건문

문법

{ % if % }

{ % elif % }

{ % else % }

{ % endif % }

 

jinja2_test.py

from flask import Flask, render_template

app = Flask(__name__)

@app.route('/if')
def info():
    name = 'Sso'
    return render_template('jinja2.html', name=name)

if __name__ == '__main__':
    app.run(host='127.0.0.1', port='8080')

jinja2.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    {% if name == 'Sso' %}
    <h3> {{name}}가 맞습니다. </h3>
    {% else %}
    <h3> {{name}}는 아닙니다.</h3>
    {% endif %}
  </body>
</html>

jinja2_test.py (좌) name = 'Sso' (우) name = 'so'

 

 

이 때 들여쓰기는 하지 않아도 된다.


주석

문법

{ # 주석처리 할 내용 # }

'WebFramework > [Flask]' 카테고리의 다른 글

[Flask] sqlalchemy create_engine 오류  (0) 2023.03.30
[Flask] Bootstrap 사용하기 (로그인)  (0) 2023.01.20
[Flask] 간단한 로그인 구현 (HTML, GET)  (0) 2023.01.20
[Flask] GET 사용법  (0) 2023.01.20
[Flask] httpi 설치  (0) 2023.01.20

Bootstrap

CSS, JS, HTML로 구성된 UI 프레임워크 중 하나

간단한 코드를 사용하면 bootstrap 프레임워크 안에서 디자인해 줌 

https://getbootstrap.com/docs/5.3/examples/

Bootstrap 페이지에 접속하여 Examples > Download examples을 통해 여러 템플릿을 사용할 수 있다.

압축을 풀고 원하는 템플릿의 index.html파일을 본인의 workspace/templates에 복사해오면 된다.

 

해당 HTML을 띄워보자.

login_test.py

from flask import Flask, jsonify, request, render_template
app = Flask(__name__)

@app.route('/login')
def login():
    id = request.args.get('id')
    pwd = request.args.get('pwd')

    if id == 'Sso':
        return_data = {'auth': 'success'}
    else:
        return_data = {'auth': 'failed'}
    return jsonify(return_data)

# HTML 렌더링
@app.route('/BS_test')
def bootstrap_html():
    return render_template('BS_login.html')

if __name__ == '__main__':
    app.run(host="127.0.0.1", port="8080")

Flask는 Jinja2 템플릿엔진을 사용한다.

render_template를 import하면 HTML을 렌더링할 수 있다.

 

이 때 렌더링 할 HTML 파일(templates 폴더 밑에 위치해야 함)과 login_test.py의 폴더 구조는 다음과 같다.

localhost://8080/BS_test로 접속해 보자

뭔가 제대로 출력되지 않는다.

HTML 파일을 확인해보자.

<link href="../assets/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="sign-in.css" rel="stylesheet">
<img class="mb-4" src="../assets/brand/bootstrap-logo.svg" alt="" width="72" height="57">

위와 같이 현재 작업 중인 폴더에는 없는 경로들이 있기 때문이다.

 

이처럼 동일한 웹 서버에서 가져와야되는 다른 파일들이 있다면 현재 작업중인 login_test.py가 있는 곳에 하위 폴더로 복사해오면 된다.

그 후 경로를 수정해주면 된다.

폴더 경로는 위와 같다.

 

다시 login_test.py 코드를 보자.

from flask import Flask, jsonify, request, render_template
app = Flask(__name__, static_url_path='/static')

@app.route('/login')
def login():
    id = request.args.get('id')
    pwd = request.args.get('pwd')

    if id == 'Sso':
        return_data = {'auth': 'success'}
    else:
        return_data = {'auth': 'failed'}
    return jsonify(return_data)

@app.route('/BS_test')
def bootstrap_html():
    return render_template('BS_login.html')

if __name__ == '__main__':
    app.run(host="127.0.0.1", port="8080")

app = Flask(__name__, static_url_path='/static')

위 코드가 추가하여 정적 파일 위치를 변경하였다.

 

이 후 HTML 코드도 경로를 수정해준다.

 

ex)

변경 전 : <link href="../assets/dist/css/bootstrap.min.css" rel="stylesheet">

변경 후 : <link href="/static/dist/css/bootstrap.min.css" rel="stylesheet">

 

다시 실행해보자.

 

구현하고 싶은건 sign in을 눌렀을 때 /login 라우터가 실행되는 것이다.

따라서 HTML파일에 가서 from 태그를 아래와 같이 수정해야 한다.

method = "get"을 추가해도 된다 (default는 get이라서 적어주지 않아도 get방식으로 동작함)

또한 변수명이 다르기 때문에 아래처럼 수정했다.

 

localhost:8080/BS_test로 접속한 후 

ID : Sso, pwd : 1234를 입력한 후 결과이다.

'WebFramework > [Flask]' 카테고리의 다른 글

[Flask] sqlalchemy create_engine 오류  (0) 2023.03.30
[Flask] Jinja2 사용법  (0) 2023.01.20
[Flask] 간단한 로그인 구현 (HTML, GET)  (0) 2023.01.20
[Flask] GET 사용법  (0) 2023.01.20
[Flask] httpi 설치  (0) 2023.01.20

로그인을 할 수 있는 간단한 form을 보자.

<form action="/login" method="get">
  <p>Enter Name:</p>
  <p><input type="text" name="user_name" /></p>
  <p><input type="submit" value="submit" /></p>
</form>

 

  • method :  HTTP method를 의미하고 여기서는 GET을 사용
  • action : 버튼이나 입력을 했을 때 가고 싶은 페이지(특정 파일, 라우팅 경로)를 입력하면 됨
  • name : 위 코드에서 보면 입력한 값이 user_name의 값으로 저장 됨
  • input의 type이 submit이면 버튼이 생성됨
    • 버튼을 누르면 위에서 입력한 변수 값(user_name)이 정해진 URL(action 값)로 전달 됨
    • 최종 URL은 '현재 HTML페이지가 실행중인 URL/login?user_name=Sso'  (method를 GET으로 지정했기 때문)

 

 

실제로 구현해보자.

 test.html

html:5 입력 후 tab을 누르면 기본 HTML5 템플릿이 생성됨

<!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>로그인 TEST</title>
</head>
<body>
  <form method="get" action="http://localhost:8080/login">
    <center>
      <h1>로그인</h1>
      ID : <input type="text" name="id" /> <br />
      PWD : <input type="text" name="pwd" /> <br />
      <input type="submit" />
    </center>
  </form>
</body>
</html>

VScode에서 Live Server를 설치한 후 오른쪽 하단에 생기는 Go Live를 클릭하면 작성한 HTML을 실시간으로 수정해가며 확인할 수 있다.

Go Live를 클릭하여 실행 후 위와 같이 사용중인 포트 번호가 나온다.

이는 별도의 서버(Live Server)를 만들어서 해당 포트(5500)에 HTML을 보여주도록 한 것이다.

위 HTML 코드 설명에서 action이 /login일 경우 127.0.0.1:5500/login으로 가게될 것이다.

하지만 이 서버에는 HTML을 출력하기 위한 것으로 login 라우팅 경로가 있는 것이 아니다!

 

action에 전체 URL을 적지 않은 경우 해당 HTML 파일을 띄운 서버에 + 라우팅 경로가 된다.

 

따라서 다른 서버로 이동하기 위해 웹 서버를 띄울 login_test.py 파일을 보자.

login_test.py

from flask import Flask, jsonify, request
app = Flask(__name__)

@app.route('/login')
def login():
    id = request.args.get('id')
    pwd = request.args.get('pwd')

    if id == 'Sso':
        return_data = {'auth': 'success'}
    else:
        return_data = {'auth': 'failed'}
    return jsonify(return_data)

if __name__ == '__main__':
    app.run(host="127.0.0.1", port="8080")

여기서는 웹서버를 127.0.0.1:8080으로 띄웠고, /login 라우팅 처리를 해줬기 때문에

위 HTML action에서 '/login'이 아닌 'http://localhost:8080/login' 로 적어줘야 한다.

 

현재는 Live Server와 login_test.py에서 띄운 서버가 총 두개 떠져 있는 것이다!

 

Live Server에서 띄운 HTML에

id : Sso , pwd : 1234을 입력하고 전송해봤다.

위와 같은 결과가 출력된다.

위 URL을 보면 /login?id=Sso&pwd=1234로 전달 됨을 알 수 있다.

'WebFramework > [Flask]' 카테고리의 다른 글

[Flask] Jinja2 사용법  (0) 2023.01.20
[Flask] Bootstrap 사용하기 (로그인)  (0) 2023.01.20
[Flask] GET 사용법  (0) 2023.01.20
[Flask] httpi 설치  (0) 2023.01.20
[Flask] 정적, 동적 페이지 라우팅  (1) 2023.01.19

[Flask] GET 사용법

2023. 1. 20. 16:08
GET 방식에서는 URL 상에서 파라미터와 파마리터 값을 넣을 수 있다.

규칙

  • URL?파라미터1=파라미터1값&파라미터2=파라미터2값
    • URL 이후 첫 파라미터 명 전에 ? 사용
    • 추가 파라미터가 있을 경우 & 사용

예시 코드

from flask import Flask, jsonify, request
app = Flask(__name__)

@app.route('/login')
def login():
    # 파라미터 변수 값 가져오기
    username = request.args.get('user_name')
    if username == 'Sso':
        return_data = {'auth': 'success'}
    else:
        return_data = {'auth': 'failed'}
    return jsonify(return_data)

if __name__ == '__main__':
    app.run(host="0.0.0.0", port="8080")

from flask import request : 파라미터 값을 flask 안에서 사용하기 위해 import 함

request.args.get(파라미터명) : GET 방식으로 가져온 파라미터 값을 사용

 

터미널 출력

(httpie 사용하기 : https://sso-y.tistory.com/55)

http GET http://localhost:8080/login?user_name=Sso
http GET http://localhost:8080/login

'WebFramework > [Flask]' 카테고리의 다른 글

[Flask] Jinja2 사용법  (0) 2023.01.20
[Flask] Bootstrap 사용하기 (로그인)  (0) 2023.01.20
[Flask] 간단한 로그인 구현 (HTML, GET)  (0) 2023.01.20
[Flask] httpi 설치  (0) 2023.01.20
[Flask] 정적, 동적 페이지 라우팅  (1) 2023.01.19

[Flask] httpi 설치

2023. 1. 20. 15:30

REST API가 잘 동작하는지 확인하기 위해서

매번 웹사이트에 들어가 URL을 입력하고 출력 화면을 보는 귀찮음을 httpi를 통해 해결해보자.

 

설치

현재 anaconda를 사용하고 있다.

anaconda prompt를 관리자 권한으로 시작한 후 아래와 같은 명령어를 입력한다.

  • pip install --upgrade pip setuptools
  • pip install --upgrade httpie

 

사용법

  • http HTTP메서드 URL
    • HTTP메서드를 쓰지 않으면, default는 GET
      • http GET http://localhost:8080/test
  •  http -v URL
    •  송신 HTTP 프로토콜 데이터도 함께 출력
    • http -v GET http://localhost:8080/test

 

Flask에서 return data를 JSON포맷으로 제공해주는 함수는 jsonify이다.

 

REST API

from flask import Flask, jsonify
app = Flask(__name__)

# data를 사전 데이터로 만들고, 이를 jsonify()메서드에 넣어서 return 해주면 됨

@app.route('/json_test')# 0.0.0.0:8080/json_test
def hello_json():
    data = {'name' : 'Sso', 'family' : 'Kim'}
    return jsonify(data)

if __name__ == '__main__':
    app.run(host='0.0.0.0', port='8080')

 

in prompt > 

 

정적 페이지 라우팅

from flask import Flask

# Flask 객체를 app에 할당
app = Flask(__name__)
# 정적 페이지 리턴
@app.route("/") # 127.0.0.1:8080
def test():
    return "<h1>Hello World!</h1>"

if __name__ == "__main__":
    app.run(host="127.0.0.1", port="8080")

 

127.0.0.1은 localhost를 의미한다.

따라서 127.0.0.1:8080으로 접속하거나 localhost:8080으로 접속하면 아래 화면과 같다.

이처럼 웹 서버에 접속하기 위해서는 포트(port)번호가 필요하다.

하지만 naver.com에 접속할 땐 포트번호를 따로 적어주지 않는다.

 

naver.com의 url은 https://www.naver.com/ 이다.

https는 뒤에 :443 포트가 자동으로 붙는다. 따라서 https://www.naver.com:443 으로 접속해도 https://www.naver.com 과 같다.

http는 :80 포트가 자동으로 붙는다.

 

동적 페이지 라우팅

from flask import Flask

app = Flask(__name__)

@app.route('/info/<name>')# 0.0.0.0:8080/info/원하는 값
def get_info(name):
    return '<h3>Hello : ' + name + '!</h3>'

if __name__ == '__main__':
    app.run(host='0.0.0.0', port='8080')

입력한 url을 변수로 사용할 수 있다.

이 경우는 데이터 타입이 없으므로 문자열로 인식한다.

 

데이터 타입이 있는 경우는 아래와 같다.

from flask import Flask

app = Flask(__name__)

@app.route('/info/<int:grade>')
def get_message(grade):
    return 'grade : %d' % grade # %d : int, %f : float, %s : string

if __name__ == '__main__':
    app.run(host='127.0.0.1', port='8080')

 

'WebFramework > [Flask]' 카테고리의 다른 글

[Flask] Jinja2 사용법  (0) 2023.01.20
[Flask] Bootstrap 사용하기 (로그인)  (0) 2023.01.20
[Flask] 간단한 로그인 구현 (HTML, GET)  (0) 2023.01.20
[Flask] GET 사용법  (0) 2023.01.20
[Flask] httpi 설치  (0) 2023.01.20