본문 바로가기

Flask-Study

플러거블 뷰(Pluggable View)

플러거블 뷰(Pluggable View)

플라스크는 기본적으로 데코레이터와 함수 기반으로 API를 작성하는데 이를 함수 기반 뷰라고 한다.

플러거블 뷰는 함수가 아닌 클래스를 기반으로한 Django 프레임워크의 Generic View에서 영향을 받은 것이다.

 

from flask import Flask, render_template

app=Flask(__name__)

@app.route('/users/')
def show_users():
    users = User.query.all()
    return render_template('users.html', users=users)

 

위 코드는 일반적으로 Flask 에서 사용하는 함수 기반 뷰이다. 이제 이 코드를 플러거블 뷰로 바꾸어 보자

변형시키는 과정은 우선 View를 상속받은 클래스를 만들어 주고 dispatch_request()를 구현해야 한다.

그다음 app.add_url_rule을 통해 URL을 등록하고, as_view() 함수에 엔드포인트 이름을 전달하여 구현한다.

이 과정대로 만든 코드가 아래 코드이다.

 

from flask import Flask, render_template
from flask.views import View

app=Flask(__name__)

class ShowUsers(View):

    def dispatch_request(self):
        users = User.query.all()
        return render_template('users.html', objects=users)

app.add_url_rule('/users/', view_func=ShowUsers.as_view('show_users'))

 

여기서 methods 변수를 사용하여 허용할 메소드를 지정할 수 있다.

 

from flask import Flask, render_template
from flask.views import View

app=Flask(__name__)

class ShowUsers(View):
    methods = ['GET', 'POST']

    def dispatch_request(self):
        users = User.query.all()
        return render_template('users.html', objects=users)

app.add_url_rule('/users/', view_func=ShowUsers.as_view('show_users'))

 

MethodView

MethodView는 get(), post(), put(), delete() 함수를 제공한다. 그래서 MethodView를 상속받으면  CRUD를 구현할 수 있게 되는 것이다. 아래는 동물 정보를 CRUD 할 수 있는 예시 코드이다. MethodView를 상속받아서 구현하였다.

 

class Animal(MethodView):
    def get(self, name):
        animal = next(filter(lambda x: x['name'] == name, animals), None)
        return {'animal' : animal}, 200 if animal else 404
    
    def post(self, name):
        #이미 존재하는 동물의 이름으로 POST 요청이 들어오면 에러 메세지와 함께 400 상태코드 리턴
        if next(filter(lambda x : x['name'] == name, animals), None):
            return {'error' : f'{name} item already exists.'}, 400
        data = request.get_json()
        new_animal = {'name' : name, 'age' : data['age']}
        animals.append(new_animal)
        return new_animal, 201
    
    def delete(self, name):
        global animals
        animal = next(filter(lambda x: x['name'] == name, animals), None)
        animals = list(filter(lambda x : x['name'] != name, animals))
        if animal:
            return {'message' : f'car <{name}> deleted successfully!'}, 200
        else:
            return {'message' : f'car <{name}> not found.'}, 404
    
    def put(self, name):
        data = request.get_json()
        animal = next(filter(lambda x: x['name'] == name, animals), None)
        if animal is None:
            animal = {'name': name, 'age' : data['age']}
            animals.append(animal)
        else:
            animal.update(data)
        return animal