読者です 読者をやめる 読者になる 読者になる

修行@ホーチミン

ホーチミン長期出張の日記です

Python API連携

前書き

PythonプロジェクトとAPIを連携するところまで確認ができたので、連携までの流れをまとめます。

Pythonプロジェクトは Pyramid と呼ばれるWEBフレームワークを用いています。

※初めて流れを追ったので認識が間違っている可能性があります。

     

全体のざっくりした流れ

  • ブラウザからHTTPリクエストを送る

  • Pythonで受け取って、リクエストを作成

  • APIにリクエストを送り、レスポンスを受け取る

  • レスポンスを加工して、テンプレートファイルをブラウザに表示する

 

 

クラスの流れメモ

 

Pythonサーバ / API を起動

ブラウザからのリクエストを受け取る為に、Pythonのサーバを起動し、 Pythonからリクエストを受け取るために、APIのサーバを起動します。

(env) username@host:~/dirname/PythonProject1$ pserve development.ini 
Starting server in PID 6660. 
Serving on http://0.0.0.0:50001

 

ブラウザからHTTPリクエスト送信

下記のURLをブラウザに入力します。

http://0.0.0.0:50001/hotel/

 

context/view.config

ここでルーティングを管理してます。

*/hotel アクセスがきた場合にHotelListContextview_hotel_list の処理を開始します。

def set_detail_setting(config):

    RootContext.set_child(
        name='hotel',
        factory=HotelListContext,
    )

    config.add_view(
        context=HotelListContext,
        view=context_as_view,
        attr='view_hotel_list',
        renderer='hotel/common/hotel/listHotel.jinja2',
        request_method='GET',
        name=''
    )

 

/context/list/list.py

Executorに処理を渡し、結果をvalidateやデータ加工して結果の受け渡しを行います。

class HotelListContext(HotelListBaseContext):

    def view_hotel_list(self):
        logger.info('Start search hotel result.')

        list_executor = Executor(self.list_service)
        list_form = self.validated_form(HotelSchema)
        response = list_executor.execute_search_products(list_form.data)
        logger.info(response)
        return {
            'data': {
                'hotels': response['body']['items'],
                'pagination': response['body']['pagination']
            }
        }

 

context/list/executor/init.py

リクエスト用のJSONを作成した後に、APIへリクエストを投げます。 レスポンスを /context/list/list.py に戻します。

class HotelSearchListExecutor(object):

    def __init__(self, service):
        self.service = service

    def execute_search_products(self, condition):
        detail_condition = {
            'header': executor_create_header_request(condition),
            'body': {
                'query': condition.get('query')
                'searchBy': condition.get('searchBy'),
                'pageNum': condition.get('pageNum'),
                'sortBy': condition.get('pageNum'),
                'sortOrder': condition.get('sortOrder')
            }
        }
        return self.service.search_hotel(detail_condition)

 

listHotel_jinja2

/context/list/list.py から渡されたJSONをjinja2で表示

※受け取ったことを確認する為の簡単なものを使います。

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Test page</title>
</head>
<body>
<table border=1>
    <tr>
        <td>id</td>
        <td>name</td>
        <td>cityCode</td>
    </tr>
    {% for item in data.hotels %}
        <tr>
            <td>{{ item.id }}</td>
            <td>{{ item.name }}</td>
            <td>{{ item.cityCode }}</td>
        </tr>
    {% endfor %}
</table>
</body>
</html>

 

流れの中で使われるメソッドや定義

development.ini

APIにリクエストを投げるときのURLを定義

URL = http://localhost:8080/hotel/

context/list/executor/init.py ⇒ self.service.search_hotel(detail_condition)

上記の処理で使われるが、ライブラリなので内容は把握できてません...。

 

executor_helper.py

context/list/executor/init.py ⇒ executor_create_header_request(condition)

上記処理で利用する、リクエストのヘッダのテンプレートです。

def executor_create_header_request(condition):

    return {
        'languageCode': 'en',
        'countryCode': 'US',
        'currencyCode': 'USD'
    }

 

schema/hotel/init.py

/context/list/list.py ⇒ self.validated_form(HotelSchema)

上記処理で使うvalidate処理です。 ここで定義していないとGETのリクエストパラメータが受け取れません。

class HotelSchema(Schema):
    allow_extra_fields = True
    filter_extra_fields = True
    query = validators.UnicodeString(not_empty=False, if_missing='')
    sortBy = validators.UnicodeString(not_empty=False, if_missing='name')
    pageNum = validators.UnicodeString(not_empty=False, if_missing='1')
    sortOrder = validators.UnicodeString(not_empty=False, if_missing='ASC')

 

ブラウザでの結果

 

f:id:bebe0909:20160920155820p:plain

DBのデータがAPIを通してブラウザ画面に表示されています。

これでPythonとAPIの連携ができたことが確認できました。