Python에서 Cloud Datastore 사용

Bookshelf 가이드의 이 페이지에서는 샘플 앱에서 영구 데이터(도서 메타데이터)를 Google Cloud Datastore에 저장하는 방법을 보여줍니다. 이 단계의 샘플 코드는 Cloud Datastore에 저장된 데이터를 만들고 읽고 업데이트하며 삭제하는(CRUD) 방법의 예를 제공합니다.

이 페이지는 여러 페이지로 구성된 가이드의 일부입니다. 처음부터 시작하여 설정 안내를 보려면 Python Bookshelf 앱으로 이동하세요.

설정 구성

이 섹션에서는 2-structured-data 디렉토리의 코드를 사용합니다. 이 디렉토리에서 파일을 수정하고 명령어를 실행하세요.

  1. 수정하기 위해 config.py를 엽니다.
  2. PROJECT_ID 값을 GCP 콘솔에 표시되는 프로젝트 ID로 설정합니다.
  3. DATA_BACKEND 값을 datastore로 설정합니다.
  4. config.py를 저장하고 닫습니다.
Cloud Datastore는 완전 관리형 서비스이며 자동으로 초기화되고 App Engine 앱에 연결되므로 추가 구성이 필요하지 않습니다.

종속 항목 설치

다음 명령어를 입력하여 가상 환경을 만들고 종속 항목을 설치합니다.

Linux/macOS

virtualenv -p python3 env
source env/bin/activate
pip install -r requirements.txt

Windows

virtualenv -p python3 env
env\scripts\activate
pip install -r requirements.txt

로컬 머신에서 앱 실행:

  1. 로컬 웹 서버를 시작합니다.

    python main.py
    
  2. 웹브라우저에서 다음 주소를 입력합니다.

    http://localhost:8080

이제 앱의 웹페이지를 찾아보고 도서를 추가, 편집, 삭제할 수 있습니다.

작업자를 종료한 다음 로컬 웹 서버를 종료하려면 Control+C를 누르세요.

App Engine 가변형 환경에 앱 배포

  1. 샘플 앱을 배포합니다.

    gcloud app deploy
    
  2. 웹브라우저에서 다음 주소를 입력합니다. [YOUR_PROJECT_ID]를 프로젝트 ID로 바꿉니다.

    https://[YOUR_PROJECT_ID].appspot.com
    

앱을 업데이트하는 경우 앱을 처음 배포할 때 사용한 같은 명령어를 입력하여 업데이트된 버전을 배포할 수 있습니다. 새로 배포하면 앱의 새 버전을 만들고 기본 버전으로 승격합니다. 이전 버전의 앱은 연결된 VM 인스턴스와 마찬가지로 유지됩니다. 이러한 모든 앱 버전과 VM 인스턴스는 청구 가능한 리소스입니다.

기본 이외의 앱 버전을 삭제하여 비용을 줄일 수 있습니다.

앱 버전을 삭제하는 방법은 다음과 같습니다.

  1. GCP Console에서 App Engine 버전 페이지로 이동합니다.

    버전 페이지로 이동

  2. 삭제할 표준이 아닌 앱 버전 옆의 확인란을 클릭합니다.
  3. 페이지 상단의 삭제 버튼을 클릭하여 앱 버전을 삭제합니다.

청구 가능한 리소스 삭제에 대한 자세한 내용은 이 가이드의 마지막 단계에서 삭제를 참조하세요.

애플리케이션 구조

Bookshelf 앱 배포 프로세스 및 구조

애플리케이션은 모든 영구 데이터를 Cloud Datastore에 저장합니다.

코드 이해하기

이 섹션에서는 애플리케이션 코드에 대해 단계별로 알아보고 이 코드의 작동 방식을 설명합니다.

양식으로 사용자 제출 처리

추가/수정 HTML 양식을 사용하면 앱 내에서 도서 제출을 추가하고 수정할 수 있습니다.

추가/수정 양식 이미지

HTML 양식은 Flask의 기본 템플릿 엔진인 Jinja2를 사용하여 작성됩니다. 다음 템플릿은 제목, 작성자, 게시 날짜, 설명에 대한 입력 필드가 있는 간단한 양식을 정의합니다.

{% extends "base.html" %}

{% block content %}
<h3>{{action}} book</h3>

<form method="POST" enctype="multipart/form-data">

  <div class="form-group">
    <label for="title">Title</label>
    <input type="text" name="title" id="title" value="{{book.title}}" class="form-control"/>
  </div>

  <div class="form-group">
    <label for="author">Author</label>
    <input type="text" name="author" id="author" value="{{book.author}}" class="form-control"/>
  </div>

  <div class="form-group">
    <label for="publishedDate">Date Published</label>
    <input type="text" name="publishedDate" id="publishedDate" value="{{book.publishedDate}}" class="form-control"/>
  </div>

  <div class="form-group">
    <label for="description">Description</label>
    <textarea name="description" id="description" class="form-control">{{book.description}}</textarea>
  </div>

  <button type="submit" class="btn btn-success">Save</button>
</form>

{% endblock %}

양식 제출 처리

사용자가 도서 추가를 클릭하면 crud.add 뷰에 양식이 표시됩니다. 사용자가 도서 추가 양식을 작성하고 저장을 클릭하면 동일 뷰에서 양식의 HTTP POST 작업이 처리됩니다. 이렇게 하면 데이터를 get_model().create 함수에 전달하여 제출된 데이터를 Cloud Datastore로 전송하는 프로세스가 시작됩니다.

@crud.route('/add', methods=['GET', 'POST'])
def add():
    if request.method == 'POST':
        data = request.form.to_dict(flat=True)

        book = get_model().create(data)

        return redirect(url_for('.view', id=book['id']))

    return render_template("form.html", action="Add", book={})

bookshelf/model_datastore.py 파일에는 Cloud Datastore에 저장된 데이터의 CRUD 기능을 수행하는 코드가 포함되어 있습니다. 예를 들어 get_model().create 문은 사용자 제출 데이터를 update 함수에 보내는 bookshelf/model_datastore.pycreate 함수를 호출합니다. 첫 번째 매개변수에 null 값이 전달되고, 이는 새 도서 제출을 의미합니다. 다음은 사용자 제출 데이터를 Cloud Datastore에 저장하는 작업을 실제로 수행하는 update 함수입니다.

def update(data, id=None):
    ds = get_client()
    if id:
        key = ds.key('Book', int(id))
    else:
        key = ds.key('Book')

    entity = datastore.Entity(
        key=key,
        exclude_from_indexes=['description'])

    entity.update(data)
    ds.put(entity)
    return from_datastore(entity)

create = update

get_client 도우미 함수는 Cloud Datastore API와 상호작용하는 클라이언트를 만듭니다.

def get_client():
    return datastore.Client(current_app.config['PROJECT_ID'])

from_datastore 도우미 함수는 데이터 저장소의 항목 키를 애플리케이션에서 사용할 수 있도록 ID로 변환하는 데 사용됩니다.

def from_datastore(entity):
    """Translates Datastore results into the format expected by the
    application.

    Datastore typically returns:
        [Entity{key: (kind, id), prop: val, ...}]

    This returns:
        {id: id, prop: val, ...}
    """
    if not entity:
        return None
    if isinstance(entity, builtin_list):
        entity = entity.pop()

    entity['id'] = entity.key.id
    return entity

사용자가 도서를 추가한 후에 도서 링크를 클릭하면 /books 페이지로 이동하여 현재 Cloud Datastore에 저장된 모든 도서를 나열합니다. model_datastore.list 함수는 Cloud Datastore에서 검색한 데이터를 사용하여 도서를 모두 나열하는 작업을 수행합니다.

def list(limit=10, cursor=None):
    ds = get_client()

    query = ds.query(kind='Book', order=['title'])
    query_iterator = query.fetch(limit=limit, start_cursor=cursor)
    page = next(query_iterator.pages)

    entities = builtin_list(map(from_datastore, page))
    next_cursor = (
        query_iterator.next_page_token.decode('utf-8')
        if query_iterator.next_page_token else None)

    return entities, next_cursor

이 코드는 datastore.Query를 사용하여 데이터 저장소를 쿼리하고 Book 항목을 모두 가져와서 title 순으로 반환합니다. 쿼리에 필터를 적용할 수도 있습니다. 자세한 내용은 Datastore 문서를 참조하세요.

query.fetch를 사용하여 쿼리에서 요청하는 반복기를 가져옵니다. 한 번에 한 페이지씩 결과를 가져오고 사용자가 결과의 다음 페이지를 로드할 수 있도록 커서를 반환합니다.

이 페이지가 도움이 되었나요? 평가를 부탁드립니다.

다음에 대한 의견 보내기...