Python+DjangoでDBの検索処理をモジュール化してみる

###共通モジュールを試してみる

[Python+Django+psycopg2で内部結合クエリを試す](https://qiita.com/tiguchi919/items/827865481e82bb32ad04)で、クエリの検索結果をdictionary化する関数を作成していますが、今回は、この関数を別パッケージのモジュールに定義して呼び出すように変更します。

####1.アプリケーションを作成する

まずは、ベースとなるアプリケーションを作成します。

```cmd.prompt
C:\Users\papa>cd c:\data\python\work
c:\data\python\work>venv\Scripts\activate
(venv) c:\data\python\work>cd project
(venv) c:\data\python\work\project>python manage.py startapp dictfetchapp
```

　(1)ディレクトリ構成

※\_\_pycache\_\_ディレクトリなどは省略しています

```
c:\data\python\work\project
│  db.sqlite3
│  manage.py
│  
├─dictfetchapp
│  │  admin.py
│  │  apps.py
│  │  models.py
│  │  tests.py
│  │  urls.py       ###追加
│  │  views.py
│  │  __init__.py
│  │  
│  ├─migrations
│  │  └─__pycache__
│  │          
│  ├─templates
│  │  └─dictfetchapp
│  │          base.html
│  │          index.html
│  │          
│  └─__pycache__
│          
├─project
│  │  settings.py
│  │  settings___.py
│  │  urls.py
│  │  wsgi.py
│  │  __init__.py
│  │  
│  └─__pycache__
│          
└─static
   ├─css
   │      bootstrap.min.css
   └─js
           bootstrap.bundle.min.js
           jquery-3.3.1.min.js

```

それぞれ、ファイルの作成、編集は[Python+Django+psycopg2で内部結合クエリを試す](https://qiita.com/tiguchi919/items/827865481e82bb32ad04)に記載していますので省略します。

###2.共通モジュールの作成

(1)アプリケーション（パッケージ）を作成します

```cmd.prompt
C:\Users\papa>cd c:\data\python\work
c:\data\python\work>venv\Scripts\activate
(venv) c:\data\python\work>cd project
(venv) c:\data\python\work\project>python manage.py startapp commons
```
同じアプリケーション内にモジュールを作成することもできますが、
今回は複数のアプリケーションで利用できるモジュールとしたいので
パッケージを作成してそこにモジュールを作成します

(2)共通モジュールを作成する

dbutils.pyファイルを作成して記述します

```
c:\data\python\work\project
│  db.sqlite3
│  manage.py
│          
├─commons
│  │  admin.py
│  │  apps.py
│  │  dbutils.py     #作成する
│  │  models.py
│  │  tests.py
│  │  views.py
│  │  __init__.py
│  │  
│  ├─migrations
│  └─__pycache__
│          
├─dictfetchapp
│      admin.py
│      apps.py
│      models.py
│      tests.py
│      urls.py
│      views.py
│      __init__.py
│  ･･･ 
├─project
│  │  settings.py
│  │  settings___.py
│  │  urls.py
│  │  wsgi.py
│  │  __init__.py
│  │  
│  └─__pycache__
│  ･･･ 
```

(3)共通モジュールの作成
作成した「dbutils.py」にクエリを実行してカーソル（dictionary化)を返す関数を定義します

```project\commons\dbutils.py
from django.db import connection


def exec_query(sqltext):
    with connection.cursor() as c:
        c.execute(sqltext)
        "Return all rows from a cursor as a dict"
        columns = [col[0] for col in c.description]
        return [
            dict(zip(columns, row))
            for row in c.fetchall()
        ]
```

(4)共通モジュールを呼び出す

views.pyを以下のように修正して共通モジュールを呼び出します。

```project\dictfetchapp\views.py
from django.shortcuts import render, get_object_or_404, redirect
from django.http import HttpResponse
from django.views.generic import ListView
from django.db import connection
from commons.dbutils import exec_query  #POINT
#list
def index(request):
    sqltext="""SELECT
        a.id
      , a.empid
      , a.empname
      , a.deptid
      , a.mailaddress
      , b.deptname
    FROM
      public.dictfetchapp_employee a
    INNER JOIN
      public.dictfetchapp_department b
      on a.deptid=b.deptid
    ORDER BY
      a.id
        ;  """
    emplist = exec_query(sqltext)

    return render(request, 'dictfetchapp/index.html', {'emplist':emplist})
```

####3.サーバを起動して動作確認してみます

```cmd.prompt
(venv) c:\data\python\work\project>manage.py runserver
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/246741/2ffa1bd1-73c5-efe5-8eab-538db1b457c3.png)


以上