Python 프레임 워크를 비교하는 시리즈의 첫 번째 부분에서 Flask에 대해 알아 봅니다.
https://opensource.com/article/18/4/flask
Python으로 웹 앱을 개발하는 경우 프레임 워크를 활용하고 있을 가능성이 있습니다. 프레임 워크는 공통 작업을 위한 재사용 가능한 코드 또는 확장을 제공하여 "안정적이고 확장 가능하며 유지 관리 가능한 웹 응용 프로그램을 구축 할 때 개발자의 삶을 더 쉽게 만드는 코드 라이브러리"입니다. Flask, Tornado, Pyramid 및 Django를 비롯한 Python 용 프레임 워크가 많이 있습니다. 새로운 Python 개발자는 종종 질문합니다. 어떤 프레임 워크를 사용해야 합니까?
이 시리즈는 개발자가 이 네 가지 프레임 워크를 비교하여 해당 질문에 답할 수 있도록 설계되었습니다. 기능과 작업을 비교하기 위해 간단한 To-Do List 웹 애플리케이션을위한 API를 구성하는 과정을 하나씩 살펴 보겠습니다. API 자체는 매우 간단합니다.
이 모든 것은 허용 된 HTTP 메서드와 함께 각 백엔드가 구현해야 하는 간단한 API 엔드 포인트 집합으로 마무리됩니다.
각 프레임 워크에는 경로, 모델,보기, 데이터베이스 상호 작용 및 전체 애플리케이션 구성을 결합하는 다른 방법이 있습니다. Flask로 시작하는 이 시리즈에서 각 프레임 워크의 이러한 측면을 설명하겠습니다.
Flask 시작 및 구성
가장 널리 사용되는 Python 라이브러리와 마찬가지로 Flask 패키지는 PPI (Python Package Index)에서 설치할 수 있습니다. 먼저 작업 할 디렉터리를 만든 다음 (flask_todo와 같은 것은 훌륭한 디렉터리 이름입니다) flask 패키지를 설치합니다. Flask 애플리케이션이 SQL 데이터베이스와 통신하는 간단한 방법을 갖도록 flask-sqlalchemy를 설치하는 것도 좋습니다.
저는 Python 3 가상 환경에서 이러한 유형의 작업을 수행하는 것을 좋아합니다. 여기로 이동하려면 명령 줄에 다음을 입력하세요.
$ mkdir flask_todo
$ cd flask_todo
$ pipenv install --python 3.6
$ pipenv shell
(flask-someHash) $ pipenv install flask flask-sqlalchemy
이것을 Git 저장소로 바꾸고 싶다면 git init를 실행하기에 좋은 곳입니다. 프로젝트의 루트가 되며, 코드베이스를 다른 컴퓨터로 내보내려는 경우 여기에 필요한 모든 설정 파일이 있으면 도움이 됩니다.
이동하는 좋은 방법은 코드베이스를 설치 가능한 Python 배포로 바꾸는 것입니다. 프로젝트의 루트에서 setup.py와 todo라는 디렉토리를 만들어 소스 코드를 보관합니다.
setup.py는 다음과 같습니다.
from setuptools import setup, find_packages
requires = [
'flask',
'flask-sqlalchemy',
'psycopg2',
]
setup(
name='flask_todo',
version='0.0',
description='A To-Do List built with Flask',
author='<Your actual name here>',
author_email='<Your actual e-mail address here>',
keywords='web flask',
packages=find_packages(),
include_package_data=True,
install_requires=requires
)
이렇게 하면 프로젝트를 설치하거나 배포 할 때마다 필요한 모든 패키지가 필요 목록에 포함됩니다. 또한 사이트 패키지에 패키지를 설정하고 설치하는 데 필요한 모든 것이 있습니다. 설치 가능한 Python 배포를 작성하는 방법에 대한 자세한 내용은 setup.py의 문서를 확인하세요.
소스 코드가 포함 된 todo 디렉터리 내에 app.py 파일과 빈 __init__.py 파일을 만듭니다. __init__.py 파일을 사용하면 설치된 패키지 인 것처럼 todo에서 가져올 수 있습니다. app.py 파일은 애플리케이션의 루트가 됩니다. 여기에 모든 Flask 애플리케이션의 장점이 있으며 해당 파일을 가리키는 환경 변수를 만듭니다. pipenv (저와 같이)를 사용하는 경우 pipenv --venv를 사용하여 가상 환경을 찾고 환경의 활성화 스크립트에서 해당 환경 변수를 설정할 수 있습니다.
# in your activate script, probably at the bottom (but anywhere will do)
export FLASK_APP=$VIRTUAL_ENV/../todo/app.py
export DEBUG='True'
Flask를 설치할 때 flask 명령 줄 스크립트도 설치했습니다. flask run을 입력하면 가상 환경의 Flask 패키지가 FLASK_APP 환경 변수가 가리키는 모든 스크립트에서 앱 개체를 사용하여 HTTP 서버를 실행하라는 메시지가 표시됩니다. 위의 스크립트에는 나중에 사용될 DEBUG라는 환경 변수도 포함되어 있습니다.
이 앱 객체에 대해 이야기 해 봅시다.
todo / app.py에서 Flask 개체의 인스턴스인 앱 개체를 만듭니다. 전체 응용 프로그램에 대한 중앙 구성 개체 역할을 합니다. 확장 된 기능 (예 : 데이터베이스 연결 및 인증 지원)에 필요한 애플리케이션의 일부를 설정하는 데 사용됩니다.
애플리케이션의 상호 작용 지점이 될 경로를 설정하는 데 정기적으로 사용됩니다. 이것이 의미하는 바를 설명하기 위해 해당하는 코드를 살펴 보겠습니다.
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
"""Print 'Hello, world!' as the response body."""
return 'Hello, world!'
이것은 가장 기본적인 완전한 Flask 응용 프로그램입니다. app은 스크립트 파일의 __name__을받는 Flask의 인스턴스입니다. 이를 통해 Python은이 파일과 관련된 파일에서 가져 오는 방법을 알 수 있습니다. app.route 데코레이터는 첫 번째보기 기능을 장식합니다. 애플리케이션에 액세스하는 데 사용되는 경로 중 하나를 지정할 수 있습니다. (나중에 살펴 보겠습니다.)
사용자가 지정하는 모든보기는 애플리케이션의 기능적 부분이 되도록 app.route로 데코 레이팅 되어야 합니다. 원하는 만큼의 기능을 응용 프로그램에 분산 시킬 수 있지만 응용 프로그램 외부에서 해당 기능에 액세스하려면 해당 기능을 장식하고 보기로 만들 경로를 지정해야 합니다.
위의 예에서 앱이 실행 중이고 http : // domainname /에서 액세스 되면 사용자는 "Hello, World!"를 수신합니다. 응답으로.
Flask에서 데이터베이스 연결
위의 코드 예제는 완전한 Flask 애플리케이션을 나타내지 만 흥미로운 것은 없습니다. 웹 애플리케이션이 할 수 있는 한 가지 흥미로운 일은 사용자 데이터를 유지하는 것이지만 데이터베이스에 대한 연결과 도움이 필요합니다.
Flask는 "스스로 수행"웹 프레임 워크입니다. 즉, 기본 제공 데이터베이스 상호 작용이 없지만 flask-sqlalchemy 패키지는 SQL 데이터베이스를 Flask 응용 프로그램에 연결합니다. flask-sqlalchemy 패키지는 SQL 데이터베이스에 연결하기 위해 데이터베이스 URL 하나만 필요합니다.
DBMS에 DBAPI-2 표준을 따르는 중개자가 있는 한 다양한 SQL 데이터베이스 관리 시스템을 flask-sqlalchemy와 함께 사용할 수 있습니다. 이 예에서는 PostgreSQL (주로 많이 사용했기 때문에)을 사용할 것이므로 Postgres 데이터베이스와 통신하는 중개자는 psycopg2 패키지입니다. psycopg2가 사용자 환경에 설치되어 있는지 확인하고 setup.py의 필수 패키지 목록에 포함 시킵니다. 다른 작업을 수행 할 필요가 없습니다. flask-sqlalchemy는 데이터베이스 URL에서 Postgres를 인식합니다.
Flask는 SQLALCHEMY_DATABASE_URI 속성을 통해 중앙 구성의 일부가 될 데이터베이스 URL이 필요합니다. 빠르고 더러운 해결책은 데이터베이스 URL을 애플리케이션에 하드 코딩하는 것입니다.
# top of app.py
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgres://localhost:5432/flask_todo'
db = SQLAlchemy(app)
그러나 이것은 지속 가능한 솔루션이 아닙니다. 데이터베이스를 변경하거나 데이터베이스 URL이 소스 제어에 표시되지 않도록 하려면 정보가 환경에 적합한 지 확인하기 위해 추가 단계를 수행해야 합니다.
환경 변수를 사용하여 더 간단하게 만들 수 있습니다. 코드가 실행되는 시스템에 관계없이 실행 중인 환경에서 구성되는 경우 항상 올바른 항목을 가리킵니다. 또한 응용 프로그램을 실행하는 데 해당 정보가 필요하더라도 소스 제어에서 하드 코딩 된 값으로 표시되지 않도록 합니다.
FLASK_APP를 선언 한 동일한 위치에서 Postgres 데이터베이스의 위치를 가리키는 DATABASE_URL을 선언합니다. 개발은 로컬에서 작동하는 경향이 있으므로 로컬 데이터베이스를 가리키면 됩니다.
# also in your activate script
export DATABASE_URL='postgres://localhost:5432/flask_todo'
이제 app.py에서 앱 구성에 데이터베이스 URL을 포함합니다.
app.config['SQLALCHEMY_DATABASE_URI'] = os.environ.get('DATABASE_URL', '')
db = SQLAlchemy(app)
그리고 마찬가지로 애플리케이션에 데이터베이스 연결이 있습니다!
Flask에서 개체 정의
대화 할 데이터베이스를 갖는 것은 좋은 첫 단계입니다. 이제 데이터베이스를 채우기 위해 몇 가지 개체를 정의 할 시간입니다.
응용 프로그램 개발에서 "모델"은 실제 또는 개념적 개체의 데이터 표현을 나타냅니다. 예를 들어 자동차 대리점을 위한 애플리케이션을 구축하는 경우 자동차의 모든 속성과 동작을 캡슐화 하는 Car 모델을 정의 할 수 있습니다.
이 경우 작업으로 할 일 목록을 작성하고 각 작업은 사용자에게 속합니다. 서로 어떻게 관련되어 있는지 너무 깊이 생각하기 전에 먼저 작업 및 사용자에 대한 개체를 정의하십시오.
flask-sqlalchemy 패키지는 SQLAlchemy를 활용하여 데이터베이스 구조를 설정하고 알려줍니다. db.Model 개체에서 상속하여 데이터베이스에 상주 할 모델을 정의하고 해당 모델의 속성을 db.Column 인스턴스로 정의합니다. 각 열에 대해 데이터 유형을 지정해야 하므로 해당 데이터 유형을 db.Column 호출에 첫 번째 인수로 전달합니다.
모델 정의는 애플리케이션 구성과 다른 개념적 공간을 차지하므로 모델 정의를 app.py와 분리하여 보관하도록 models.py를 만드십시오. 태스크 모델은 다음 속성을 갖도록 구성되어야 합니다.
Task 개체에 대한이 속성 목록이 주어지면 응용 프로그램의 Task 개체를 다음과 같이 정의 할 수 있습니다.
from .app import db
from datetime import datetime
class Task(db.Model):
"""Tasks for the To Do list."""
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.Unicode, nullable=False)
note = db.Column(db.Unicode)
creation_date = db.Column(db.DateTime, nullable=False)
due_date = db.Column(db.DateTime)
completed = db.Column(db.Boolean, default=False)
def __init__(self, *args, **kwargs):
"""On construction, set date of creation."""
super().__init__(*args, **kwargs)
self.creation_date = datetime.now()
클래스 생성자 메서드의 확장에 유의하십시오. 하루가 끝나면 생성하는 모델은 여전히 Python 객체이므로 인스턴스화 하려면 생성을 거쳐야 합니다. 모델 인스턴스의 생성 날짜가 실제 생성 날짜를 반영하는지 확인하는 것이 중요합니다. "이 모델의 인스턴스가 생성되면 날짜와 시간을 기록하고 생성 날짜로 설정하십시오"라고 효과적으로 말하여 해당 관계를 명시 적으로 설정할 수 있습니다.
모델 관계
주어진 웹 애플리케이션에서 객체 간의 관계를 표현할 수 있기를 원할 수 있습니다. To-Do List 예제에서 사용자는 여러 작업을 소유하고 각 작업은 한 명의 사용자 만 소유합니다. 이것은 작업이 "다"이고 해당 작업을 소유 한 사용자가 "일"인 외래 키 관계라고도 하는 "다 대일"관계의 예입니다.
Flask에서는 db.relationship 함수를 사용하여 다 대일 관계를 지정할 수 있습니다. 먼저 User 개체를 만듭니다.
class User(db.Model):
"""The User object that owns tasks."""
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.Unicode, nullable=False)
email = db.Column(db.Unicode, nullable=False)
password = db.Column(db.Unicode, nullable=False)
date_joined = db.Column(db.DateTime, nullable=False)
token = db.Column(db.Unicode, nullable=False)
def __init__(self, *args, **kwargs):
"""On construction, set date of creation."""
super().__init__(*args, **kwargs)
self.date_joined = datetime.now()
self.token = secrets.token_urlsafe(64)
Task 개체와 매우 유사합니다. 대부분의 개체는 테이블 열과 동일한 기본 형식의 클래스 속성을 가집니다. 때때로, 당신은 다중 상속 마법을 포함하여 조금 다른 무언가를 마주하게 될 것입니다. 그러나 이것이 표준입니다.
이제 사용자 모델이 생성되었으므로 외래 키 관계를 설정할 수 있습니다. "다"의 경우 이 작업을 소유 한 사용자의 user_id 및 해당 ID를 가진 사용자 개체에 대한 필드를 설정합니다. 또한 작업이 사용자를 소유자로 가져올 때 사용자 모델을 업데이트하는 키워드 인수 (back_populates)를 포함해야 합니다.
"1"의 경우 특정 사용자가 소유 한 작업에 대한 필드를 설정합니다. Task 개체에서 양방향 관계를 유지하는 것과 유사하게 사용자에게 할당 될 때 Task를 업데이트하도록 사용자의 관계 필드에 키워드 인수를 설정합니다.
# on the Task object
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
user = db.relationship("user", back_populates="tasks")
# on the User object
tasks = db.relationship("Task", back_populates="user")
데이터베이스 초기화
이제 모델 및 모델 관계가 설정되었으므로 데이터베이스 설정을 시작하십시오. Flask에는 자체 데이터베이스 관리 유틸리티가 포함되어 있지 않으므로 자체적으로 작성해야 합니다 (어느 정도). 당신은 그것에 대해 화려하게 될 필요가 없습니다. 생성 할 테이블을 인식 할 수 있는 무언가와 생성 할 코드가 필요합니다 (또는 필요할 경우 삭제). 데이터베이스 테이블에 대한 업데이트 처리 (예 : 데이터베이스 마이그레이션)와 같이 좀 더 복잡한 작업이 필요한 경우 Flask-Migrate 또는 Flask-Alembic과 같은 도구를 살펴 보는 것이 좋습니다.
데이터베이스 관리를 위해 setup.py 옆에 initializedb.py라는 스크립트를 만듭니다. (물론 이것을 호출 할 필요는 없지만 파일의 기능에 적합한 이름을 지정하지 않는 이유는 무엇입니까?) initializedb.py 내에서 app.py에서 db 객체를 가져 와서 테이블을 생성하거나 삭제하는 데 사용합니다. initializedb.py는 다음과 같이 표시되어야 합니다.
from todo.app import db
import os
if bool(os.environ.get('DEBUG', '')):
db.drop_all()
db.create_all()
DEBUG 환경 변수가 설정된 경우 테이블을 삭제하고 다시 빌드 하십시오. 그렇지 않으면 표를 한 번만 생성하면 됩니다.
보기 및 URL 구성
전체 애플리케이션을 연결하는 데 필요한 마지막 비트는 보기와 경로입니다. 웹 개발에서 "보기"(개념 상)는 애플리케이션의 특정 액세스 포인트 ( "경로")에 도달 할 때 실행되는 기능입니다. 이러한 액세스 포인트는 URL (일부 데이터를 반환하거나 제공된 일부 데이터를 처리하는 응용 프로그램의 기능에 대한 경로)로 나타납니다. 뷰는 주어진 클라이언트의 특정 HTTP 요청을 처리하고 해당 클라이언트에 일부 HTTP 응답을 반환하는 논리적 구조입니다.
Flask에서 뷰는 함수로 나타납니다. 예를 들어 위의 hello_world보기를 참조하십시오. 단순화를 위해 여기에 다시 있습니다.
@app.route('/')
def hello_world():
"""Print 'Hello, world!' as the response body."""
return 'Hello, world!'
http : // domainname / 경로에 액세스하면 클라이언트는 "Hello, world!"라는 응답을 받습니다.
Flask를 사용하면 함수가 app.route로 장식 될 때 뷰로 표시됩니다. 차례로 app.route는 지정된 경로의 맵을 해당 경로에 액세스 할 때 실행되는 함수로 애플리케이션의 중앙 구성에 추가합니다. 이를 사용하여 나머지 API 빌드를 시작할 수 있습니다.
GET 요청 만 처리하는 보기로 시작하고 액세스 할 수 있는 모든 경로와 액세스에 사용할 수 있는 방법을 나타내는 JSON으로 응답합니다.
from flask import jsonify
@app.route('/api/v1', methods=["GET"])
def info_view():
"""List of routes for this API."""
output = {
'info': 'GET /api/v1',
'register': 'POST /api/v1/accounts',
'single profile detail': 'GET /api/v1/accounts/<username>',
'edit profile': 'PUT /api/v1/accounts/<username>',
'delete profile': 'DELETE /api/v1/accounts/<username>',
'login': 'POST /api/v1/accounts/login',
'logout': 'GET /api/v1/accounts/logout',
"user's tasks": 'GET /api/v1/accounts/<username>/tasks',
"create task": 'POST /api/v1/accounts/<username>/tasks',
"task detail": 'GET /api/v1/accounts/<username>/tasks/<id>',
"task update": 'PUT /api/v1/accounts/<username>/tasks/<id>',
"delete task": 'DELETE /api/v1/accounts/<username>/tasks/<id>'
}
return jsonify(output)
뷰에서 특정 유형의 HTTP 요청을 처리하기를 원하므로 app.route를 사용하여 해당 제한을 추가하십시오. methods 키워드 인수는 각 문자열에 가능한 HTTP 메서드 유형이 있는 문자열 목록을 값으로 사용합니다. 실제로, app.route를 사용하여 하나 이상의 HTTP 요청 유형으로 제한하거나 methods 키워드 인수 만 남겨 두어 모든 유형을 수락 할 수 있습니다.
뷰 함수에서 반환하려는 모든 것은 적절한 형식의 HTTP 응답을 구성 할 때 Flask가 문자열로 변환하는 문자열 또는 객체 여야 합니다. 이 규칙에 대한 예외는 애플리케이션에서 발생한 리디렉션 및 예외를 처리하려고 할 때입니다. 이것이 개발자에게 의미하는 바는 클라이언트로 다시 보내려는 모든 응답을 문자열로 해석 할 수 있는 것으로 캡슐화 할 수 있어야 한다는 것입니다.
복잡성을 포함하지만 여전히 문자열화할 수 있는 좋은 구조는 Python 사전입니다. 따라서 클라이언트에 데이터를 보내고 싶을 때마다 정보를 전달하는 데 필요한 키-값 쌍이 있는 Python 사전을 선택하는 것이 좋습니다. 해당 사전을 올바른 형식의 JSON 응답, 헤더 및 모두로 전환하려면 Flask의 jsonify 함수에 인수로 전달합니다 (flask import jsonify에서).
위의 보기 기능은 이 API가 처리하려는 모든 경로의 목록을 효과적으로 가져와 http : // domainname / api / v1 경로에 액세스 할 때마다 클라이언트로 보냅니다. Flask는 그 자체로 정확히 일치하는 URI에 대한 라우팅을 지원하므로 동일한 경로에 후행 /로 액세스하면 404 오류가 발생합니다. 동일한 뷰 함수로 둘 다 처리하려면 다음과 같은 스택 데코레이터가 필요합니다.
@app.route('/api/v1', methods=["GET"])
@app.route('/api/v1/', methods=["GET"])
def info_view():
# blah blah blah more code
흥미로운 경우는 정의 된 경로에 후행 슬래시가 있고 클라이언트가 슬래시 없이 경로를 요청하면 데코레이터를 두 배로 늘릴 필요가 없다는 것입니다. Flask는 클라이언트의 요청을 적절하게 리디렉션 합니다. 두 가지 방식으로 작동하지 않는 것이 이상합니다.
Flask 요청 및 DB
기본적으로 웹 프레임 워크의 역할은 들어오는 HTTP 요청을 처리하고 HTTP 응답을 반환하는 것입니다. 이전에 작성된 뷰는 액세스 된 URI를 제외하고는 HTTP 요청과 실제로 관련이 없습니다. 데이터를 처리하지 않습니다. 데이터를 처리해야 할 때 Flask가 어떻게 작동하는지 살펴 보겠습니다.
가장 먼저 알아야 할 것은 Flask가 각 뷰 함수에 별도의 요청 객체를 제공하지 않는다는 것입니다. 모든 보기 함수에서 사용할 수 있는 하나의 전역 요청 개체가 있으며 해당 개체는 편리하게 request라는 이름을 지정하며 Flask 패키지에서 가져올 수 있습니다.
다음은 Flask의 경로 패턴이 조금 더 뉘앙스를 가질 수 있다는 것입니다. 한 가지 시나리오는 보기 기능을 활성화하기 위해 완벽하게 일치해야 하는 하드 코딩 된 경로입니다. 또 다른 시나리오는 여러 경로를 처리 할 수 있는 경로 패턴으로, 해당 경로의 일부를 가변적으로 허용하여 모두 하나의 뷰에 매핑 됩니다. 문제의 경로에 변수가 있는 경우 해당 값은 보기의 매개 변수 목록에 있는 동일한 이름의 변수에서 액세스 할 수 있습니다.
@app.route('/a/sample/<variable>/route)
def some_view(variable):
# some code blah blah blah
보기 내에서 데이터베이스와 통신하려면 스크립트 상단에 채워진 db 개체를 사용해야 합니다. 세션 속성은 변경할 때 데이터베이스에 대한 연결입니다. 객체 만 쿼리 하려는 경우 db.Model에서 빌드 된 객체에는 쿼리 속성을 통해 자체 데이터베이스 상호 작용 계층이 있습니다.
마지막으로, 문자열보다 더 복잡한 뷰에서 원하는 모든 응답은 의도적으로 작성되어야 합니다. 이전에는 "jsonified"사전을 사용하여 응답을 작성했지만 특정 가정이 만들어졌습니다 (예 : 200 상태 코드, 상태 메시지 "OK", "text / plain"의 Content-Type). HTTP 응답에 원하는 특수 소스는 의도적으로 추가해야 합니다.
Flask보기 작업에 대한 이러한 사실을 알면 새 Task 개체를 만드는 작업이 있는 보기를 구성 할 수 있습니다. 코드 (아래)를 보고 하나씩 해결해 봅시다.
from datetime import datetime
from flask import request, Response
from flask_sqlalchemy import SQLAlchemy
import json
from .models import Task, User
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = os.environ.get('DATABASE_URL', '')
db = SQLAlchemy(app)
INCOMING_DATE_FMT = '%d/%m/%Y %H:%M:%S'
@app.route('/api/v1/accounts/<username>/tasks', methods=['POST'])
def create_task(username):
"""Create a task for one user."""
user = User.query.filter_by(username=username).first()
if user:
task = Task(
name=request.form['name'],
note=request.form['note'],
creation_date=datetime.now(),
due_date=datetime.strptime(due_date, INCOMING_DATE_FMT) if due_date else None,
completed=bool(request.form['completed']),
user_id=user.id,
)
db.session.add(task)
db.session.commit()
output = {'msg': 'posted'}
response = Response(
mimetype="application/json",
response=json.dumps(output),
status=201
)
return response
@ app.route 데코레이터부터 시작하겠습니다. 경로는 '/ api / v1 / accounts / <username> / tasks'이며 여기서 <username>은 경로 변수입니다. 변수가 될 경로의 모든 부분을 꺾쇠 괄호로 묶은 다음 같은 이름의 매개 변수 목록에서 다음 줄에 경로의 해당 부분을 포함합니다. 매개 변수 목록에 있어야 하는 유일한 매개 변수는 경로의 변수 여야 합니다.
다음은 쿼리입니다.
user = User.query.filter_by(username=username).first()
사용자 이름으로 한 사용자를 찾으려면 개념적으로 데이터베이스에 저장된 모든 사용자 개체를 보고 요청 된 사용자 이름과 일치하는 사용자를 찾아야 합니다. Flask를 사용하면 쿼리 속성을 통해 기준과 일치하는 인스턴스에 대한 사용자 개체를 직접 요청할 수 있습니다. 이 유형의 쿼리는 객체 목록을 제공하므로 (단 하나의 객체이거나 전혀 없는 경우에도) 원하는 객체를 얻으려면 first ()를 호출하면 됩니다.
task = Task(
name=request.form['name'],
note=request.form['note'],
creation_date=datetime.now(),
due_date=datetime.strptime(due_date, INCOMING_DATE_FMT) if due_date else None,
completed=bool(request.form['completed']),
user_id=user.id,
)
사용 된 HTTP 메서드에 관계없이 데이터가 응용 프로그램으로 전송 될 때마다 해당 데이터는 요청 개체의 양식 속성에 저장됩니다. 프런트 엔드의 필드 이름은 양식 사전의 해당 데이터에 매핑 된 키 이름이 됩니다. 항상 문자열 형식으로 제공되므로 데이터를 특정 데이터 유형으로 지정하려면 적절한 유형으로 캐스팅 하여 명시 적으로 만들어야 합니다.
주의해야 할 또 다른 사항은 새로 인스턴스화 된 태스크에 현재 사용자의 사용자 ID를 할당하는 것입니다. 이것이 외래 키 관계가 유지되는 방법입니다.
db.session.add(task)
db.session.commit()
새 Task 인스턴스를 만드는 것은 좋지만 그 구성은 데이터베이스의 테이블에 대한 고유 한 연결이 없습니다. 해당 SQL 테이블에 새 행을 삽입하려면 db 개체에 연결된 세션을 사용해야 합니다. db.session.add (task)는 테이블에 추가 할 새 Task 인스턴스를 스테이징 하지만 아직 추가하지는 않습니다. 여기서는 한 번만 수행되지만 커밋 하기 전에 원하는 만큼 추가 할 수 있습니다. db.session.commit ()은 모든 단계적 변경 또는 "커밋"을 가져 와서 데이터베이스의 해당 테이블에 적용합니다.
output = {'msg': 'posted'}
response = Response(
mimetype="application/json",
response=json.dumps(output),
status=201
)
응답은 MIME 유형, 본문 및 상태가 의도적으로 설정된 Response 개체의 실제 인스턴스입니다. 이보기의 목표는 새로운 것을 만든 사용자에게 경고하는 것입니다. 이 뷰가 JSON을 보내고 받는 백엔드 API의 일부로 간주되는 방식을 확인하면 응답 본문이 JSON 직렬화 가능해야 합니다. 간단한 문자열 메시지가 있는 사전이면 충분합니다. 사전에서 json.dumps를 호출하여 전송할 준비가 되었는지 확인하세요. 그러면 Python 객체가 유효한 JSON으로 바뀝니다. jsonify는 입력을 응답 본문으로 사용하여 실제 응답 객체를 구성하므로 jsonify 대신 사용됩니다. 반대로 json.dumps는 주어진 Python 객체를 가져와 가능한 경우 유효한 JSON 문자열로 변환합니다.
기본적으로 Flask로 전송되는 응답의 상태 코드는 200입니다. 이는 특정 리디렉션 수준 또는 오류 수준 메시지를 다시 보내려고 하지 않는 대부분의 상황에서 작동합니다. 이 경우 새 항목이 생성 된 시기를 프런트 엔드에 명시 적으로 알려 주므로 상태 코드를 201로 설정합니다. 이는 새 항목을 만드는 것에 해당합니다.
그리고 그게 다야! 현재 To-Do List 애플리케이션 설정을 고려할 때 Flask에서 새 Task 개체를 만들기 위한 기본보기입니다. 작업을 나열, 편집 및 삭제하기 위해 유사한 보기를 구성 할 수 있지만 이 예제는 수행 방법에 대한 아이디어를 제공합니다.
더 큰 그림
새로운 것을 만들기 위한 하나의 보기보다 애플리케이션에 들어가는 것이 훨씬 더 많습니다. 권한 부여 / 인증 시스템, 테스트, 데이터베이스 마이그레이션 관리, 교차 출처 리소스 공유 등에 대해 논의한 적은 없지만, 위의 세부 정보는 자신의 Flask 애플리케이션 구축을 시작하기에 충분할 것입니다.
등록된 댓글이 없습니다.