AzureのTable ストレージを使ったDjango(PTVS)アプリの作成とデプロイ

#TableストレージのNoSQLデータストアとは
NoSQL（一般に "Not only SQL" と解釈される）とは、関係データベース管理システム (RDBMS) 以外のデータベース管理システムを指すおおまかな分類語 
NoSQL系データベース管理システムには、データの格納および取得が高度に最適化されているものが多い。その最適化のために機能性を最小限にしているものもある。「値」およびそれを取得するための「キー」だけを格納できるKey-Value型データベースは、その最たる例である。wikiより
NoSQLデータベース環境とは、簡単に言えば、幅広い種類の膨大な量のデータを高速かつ動的に整理し分析することを可能にする、非リレーショナルな広域分散データベースシステムです。[引用](https://academy.datastax.com/what-is-nosql-jp)
このNoSQLを使ったストレージサービスをNoSQLデータストアといいAzure上で提供されている。

#Djangoのアプリケーション作成
[前回](http://qiita.com/saiyuki1919/items/61b6c666aecd7c313e47)の続きになります。
NoSQLを使うためのPythonのパッケージの解説をしてきます。
一部解説しますが、詳しくは[こちら](https://github.com/yuesan/azure-content-jajp/blob/master/articles/storage/storage-python-how-to-use-table-storage.md)

##Python Azure Storage パッケージ
**テーブル作成**
**TableService**：Azure上のNoSQLデータストアにアクセス
**create_table**：テーブルを作成

```
account_name = 'ストレージのアカウント名'
account_key = 'key(複数あるkeyのどれかで良い)'
table_service = TableService(account_name=account_name, account_key=account_key)
table_service.create_table('mytasks')
```

**抽出**
**table_service.query_entities('テーブル名','','レコード指定')**
SQLに直すと：**Select name,category From mytasks;**


```
tasks = table_service.query_entities('mytasks', '', 'name,category')
for task in tasks:
    print(task.name)
    print(task.category)
```

**挿入**
※PartitionKeyとRowKeyを指定する必要があることに注意してください
**PartitionKey**が同じエンティティは同じノードに格納されます。**RowKey**は、エンティティが属するパーティション内のエンティティの一意のID

```
table_service.insert_entity('mytasks', {'PartitionKey':name+category, 'RowKey':name, 'name':name, 'category':category})     
```

**置き換える**
エンティティ内に存在していれば置き換え、なければ挿入
第二引数、第三引数は同様に**PartitionKey**と**RowKey**を指定

```
task = {'name':YUKI, 'category':Friends}
table_service.insert_or_replace_entity('mytasks', name+category, name, task)
```

**更新**
**PartitionKey**と**RowKey**を指定して、レコードを更新できる

```
table_service.update_entity('mytasks', partition_key, row_key, {'name': name, 'category':category})
```

**エンティティの削除**
エンティティを削除する場合は**PartitionKey**と**RowKey**を指定することで削除できる

```
table_service.delete_entity('mytasks',name+category,name)
```

**テーブル削除**

```
table_service.delete_table('tasktable')
```

##Djangoアプリケーション作成
[前回](http://qiita.com/saiyuki1919/items/61b6c666aecd7c313e47)のを少し改造して、削除機能を追加した。

```Python:views.py
from django.shortcuts import render
from django.http import HttpRequest
from django.template import RequestContext
from datetime import datetime

from django.http import HttpResponse
from django.template.loader import render_to_string
from azure.storage.table import TableService, Entity

account_name = 'ストレージ名'
account_key = 'ストレージのkey'
table_service = TableService(account_name=account_name, account_key=account_key)
table_service.create_table('mytasks')

def list_tasks(request):      
    entities = table_service.query_entities('mytasks', '', 'name,category')
    html = render_to_string('app/test.html', {'entities':entities})     
    return HttpResponse(html)
 
 
def add_task(request):     
    name = request.GET['name']     
    category = request.GET['category']        
    table_service.insert_entity('mytasks', {'PartitionKey':name+category, 'RowKey':name, 'name':name, 'category':category})     
    entities = table_service.query_entities('mytasks', '', 'name,category')     
    html = render_to_string('app/test.html', {'entities':entities})     
    return HttpResponse(html)
 

def update_task(request):     
    name = request.GET['name']     
    category = request.GET['category']
    table_service.delete_entity('mytasks',name+category,name)
    entities = table_service.query_entities('mytasks', '', 'name,category')         
    html = render_to_string('app/test.html', {'entities':entities})     
    return HttpResponse(html)
```

```HTML:test.html
<!DOCTYPE html>
<html>
    <head>
        <title></title>
    </head>     
    <body>
        <h2>My Tasks</h2> <br>     
        <table border="1">
            <tr>
                <td>Name</td>
                <td>Category</td>
                <td>Check</td>
            </tr>     
            {% for entity in entities %}     
                <form action="update_task" method="GET">
                    <tr>
                        <td>{{entity.name}} <input type="hidden" name='name' value="{{entity.name}}"></td>     
                        <td>{{entity.category}} <input type="hidden" name='category' value="{{entity.category}}"></td>   
                        <td><input type="submit" value="削除"></td> 
                    </tr>     
                </form>     
            {% endfor %}     
        </table>     
        <br>     
        <hr>    
        <table border="1">
            <form action="add_task" method="GET">
                <tr>
                    <td>Name:</td
                    ><td><input type="text" name="name"></input></td>
                </tr>     
                <tr>
                    <td>Category:</td>
                    <td><input type="text" name="category"></input></td>
                </tr>     
                <tr>
                    <td><input type="submit" value="add task"></input></td>
                </tr>     
            </form>     
        </table>     
    </body>     
</html>
```

```Python:urls.py
urlpatterns = [
    url(r'^$', 'app.views.list_tasks'),
    url(r'^list_tasks$', 'app.views.list_tasks'),
    url(r'^add_task$', 'app.views.add_task'),
    url(r'^update_task$', 'app.views.update_task'),
]
```

##実行
新しく実装した削除機能のみを試す
削除ボタンを押すとレコードが削除される

**※実際に調べた限り、Azure上のストレージでテーブルやレコードの削除をすることができません。テーブル削除をAzure上で行いたいのであれば、ストレージを作り直すという手もあります。ただ、めんどくさいし、大変なので、プログラム上で(パッケージを使って)削除することをお勧めします。**

<img width="953" alt="１.png" src="https://qiita-image-store.s3.amazonaws.com/0/130097/bc4a6386-86dc-976f-7baf-0ad7c59956c0.png">

<img width="953" alt="２.png" src="https://qiita-image-store.s3.amazonaws.com/0/130097/85f8948b-6129-315c-deae-8cc787324c7d.png">

#Tableストレージを使ったDjangoアプリをAzure上にデプロイ
プロジェクトを右クリックし、**【公開】**を選択
<img width="1051" alt="1.png" src="https://qiita-image-store.s3.amazonaws.com/0/130097/ef723460-1a7e-5fca-0e24-6845526518fb.png">

Microsoft Azure Web Appsを選択し**【発行】**
<img width="704" alt="2.png" src="https://qiita-image-store.s3.amazonaws.com/0/130097/a89f98bd-dcf4-7a4b-b96d-f8f6e5c3d89b.png">

【New】で新しいアプリを作成します！
<img width="586" alt="3.png" src="https://qiita-image-store.s3.amazonaws.com/0/130097/5deb9140-addd-11e6-5b8b-050a293730df.png">

**Web App name**と**App service plan**に任意の名前をつける
**Resource group**はなければ作成してください
<img width="636" alt="4.png" src="https://qiita-image-store.s3.amazonaws.com/0/130097/e049e385-43d8-310d-e702-a73f300ef0b9.png">

基本的に確認のみで、細かい設定をしたい方は**【次へ】**を選択
問題ないのでそのまま**【発行】**
すると、Azure上にUPされる
<img width="702" alt="5.png" src="https://qiita-image-store.s3.amazonaws.com/0/130097/39a96c7b-f982-b5d0-4b93-338bcd00a0e2.png">

最後にAzureのポータル管理画面から
【App Service】➡︎【作成したAPP名】➡︎【概要】➡︎【URL】
を選択すると先ほど作成したDjangoアプリケーションが動く！！
![6.png](https://qiita-image-store.s3.amazonaws.com/0/130097/08424bc1-d462-c64c-60eb-5c3a78614656.png)