1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

はじめに

こんにちは。@toamoku-20220418と申します。現在Djangoを使用したアプリケーションの作成を目標に、勉強を進めております。
そこで今回はDjangoのデータベースにPostgreSQLを使用して、簡単なサンプルアプリを作成しました。PostgreSQLをどのようにして使用すればいいかを解説しておりますので、ぜひ最後までご覧いただき、皆さんの参考になれば幸いです。

前提条件

PCにはpythonがインストールされていることやpythonの文法などの解説は省いております。そして今回は環境変数を使用しますので、私の下記の記事をご覧ください。また使用PCはmacです。

今回の目標

PostgreSQLをDjangoの環境で使用できるようになること。

PostgreSQLのインストール

Homebrewでインストールを行いますので、Homebrewがインストールされていない方は下記を参考にしてインストールしてください。

次にHomebrewをアップデートしましょう。

$ brew --version
$ brew update
$ brew upgrade

続いてインストール可能なPostgreSQLを確認し、インストールを行います。

# インストール可能なPostgreSQLを確認
$ brew search postgresql

# PostgreSQLをインストール
$ brew install postgresql

PostgreSQLのバージョンを確認してみましょう。

$ psql --version

PostgreSQLの設定

最初にPostgreSQLを起動します。

$ brew services start postgresql

データベースに接続してみましょう。

$ psql postgres

最初にデータベースを作成します。

postgres=# CREATE DATABASE mydatabase;

続いてユーザーを作成します。

postgres=# CREATE USER myuser WITH PASSWORD 'mypassword';

作成したユーザーに権限を付与します。

postgres=# GRANT ALL PRIVILEGES ON DATABASE mydatabase TO myuser;

ここで一旦接続を終了しましょう。

postgres=# \q

これで下記の作成を終わりました。

  • データベース:mydatabase
  • ユーザー:myuser
  • 権限:myuserにmydatabaseの操作権限を付与

Djangoのセットアップ

続いてDjangoのセットアップを行います。
最初にルートディレクトリにプロジェクトディレクトリを作成して、移動します。

$ mkdir myproject
$ cd myproject

仮想環境(virtualenvを使用)を作成して、DjangoとPostgreSQLを使用するためのライブラリをインストールします。環境変数も使用するので、python-dotenvも一緒にインストールします。

仮想環境の作成
$ virtualenv psqlenv

仮想環境を有効化
$ source psqlenv/bin/activate

Djangoなどをインストール
$ pip install django psycopg2-binary python-dotenv

Djangoプロジェクトとアプリの作成を行います。

$ django-admin manage.py startproject myproject .

$ python manage.py startapp myapp

PostgreSQLの設定

Djangoのデータベース設定を、SQLiteからPostgreSQLに変更します。

settings.py
# myproject/settings.py

import os # 追加
from pathlib import Path
from dotenv import load_dotenv # 追加

load_dotenv() # 追加

INSTALLED_APPS = [
     :
    'myapp', # 追加
]

# DATABASEを下記に変更
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': os.getenv('DB_NAME'), # .envから
        'USER': os.getenv('DB_USER'), # .envから
        'PASSWORD': os.getenv('DB_PASSWORD'), # .envから
        'HOST': 'localhost',  # デフォルトは 'localhost'
        'PORT': '5432',       # デフォルトは '5432'
    }
}

# 定番の変更
LANGUAGE_CODE = 'ja'

TIME_ZONE = 'Asia/Tokyo'

.envファイルを作成し、にPostgreSQLのユーザー名やパスワードをここで管理します。

.env
# .env

DB_NAME=mydatabase
DB_USER=myuser
DB_PASSWORD=mypassword

これでDjangoのデータベースにPostgreSQLを設定することができました。

PostgreSQLを使用

簡単なアプリを作成して、ちゃんと動いているか確認してみましょう。
最初にモデルを作成します。

models.py
# myapp/models.py

from django.db import models

# Create your models here.
class Book(models.Model):
    title = models.CharField(max_length=30)
    author = models.CharField(max_length=30)
    
    def __str__(self):
        return self.title

フォームも作成しちゃいます。

forms.py
# myapp/models.py

from django import forms
from .models import Book # ここを追加

class BookForm(forms.ModelForm):
    
    class Meta:
        model = Book
        fields = ['title', 'author']

続いてビューもいっきに作成しちゃいましょう。CRUDの処理をクラスベースビューを使用して作成しちゃいます。

views.py
# myapp/views.py

from django.shortcuts import render
from django.urls import reverse_lazy
from django.views.generic import ListView, DetailView, CreateView, UpdateView, DeleteView
from .models import Book
from .forms import BookForm

# ホーム画面
def home(request):
    return render(request, 'home.html')

# ListViewで一覧画面
class BookListView(ListView):
    model = Book
    template_name = 'book_list.html'

# DetailViewで詳細画面
class BookDetailView(DetailView):
    model = Book
    template_name = 'book_detail.html'

# CreateViewで新規登録
class BookCreateView(CreateView):
    model = Book
    form_class = BookForm
    template_name = 'book_form.html'
    success_url = reverse_lazy('book-list')

# UpdateViewで編集画面
class BookUpdateView(UpdateView):
    model = Book
    form_class = BookForm
    template_name = 'book_update.html'
    success_url = reverse_lazy('book-list')

# DeleteViewで削除画面
class BookDeleteView(DeleteView):
    model = Book
    template_name = 'book_delete.html'
    success_url = reverse_lazy('book-list')

今度はurls.pyを編集します。myprojectとmyappの両方を一度にやっちゃいましょう。

urls.py
# myproject/urls.py

from django.contrib import admin
from django.urls import path, include # include追加

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('myapp.urls')), # 追加 
]


# myapp/urls.py

from django.urls import path
from . import views

urlpatterns = [
    path('', views.home, name='home'), # ホーム
    path('books/', views.BookListView.as_view(), name='book-list'), # リスト
    path('books/<int:pk>/', views.BookDetailView.as_view(), name='book-detail'), # 詳細
    path('books/new/', views.BookCreateView.as_view(), name='book-create'), # 新規登録
    path('books/update/<int:pk>/', views.BookUpdateView.as_view(), name='book-update'), # 編集
    path('books/delete/<int:pk>/', views.BookDeleteView.as_view(), name='book-delete'), # 削除
]

templatesディレクトリを作成し、各htmlを作成します。ちょっとだけBootstrapを使用しています。
まずはbase.htmlから

base.html
<!-- templates/base.html -->

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-9ndCyUaIbzAi2FUVXJi0CjmCapSmO7SnpJef0486qhLnuZ2cdeRhO02iuK6FUUVM" crossorigin="anonymous">
    <title>{% block title %}{% endblock %}</title>
</head>
<body class="container">
    <nav class="navbar navbar-expand-lg bg-body-tertiary">
        <div class="container-fluid">
            <a class="navbar-brand" href="{% url 'home' %}">BOOKS</a>
            <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
                <span class="navbar-toggler-icon"></span>
            </button>
            <div class="collapse navbar-collapse" id="navbarNav">
                <ul class="navbar-nav">
                    <li class="nav-item">
                        <a class="nav-link active" aria-current="page" href="{% url 'home' %}">ホーム</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" href="{% url 'book-list' %}">リスト</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" href="{% url 'book-create' %}">新規登録</a>
                    </li>
                </ul>
            </div>
        </div>
    </nav>
    <div class="row">
        <div class="col-md-6 mx-auto">
    {% block content %}
    {% endblock %}
        </div>
    </div>
    <!-- Bootstrap -->
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-geWF76RCwLtnZ8qwWowPQNguL3RmwHVBC9FhGdlKrxdiJJigb/j/68SIy3Te4Bkz" crossorigin="anonymous"></script>
</body>
</html>

ホーム画面 home.html

home.html
<!-- templates/home.html -->

{% extends "base.html" %}
{% block title %}home{% endblock %}
{% block content %}
<h1>ホーム画面だよ</h1>
<p>クラスベースビューを使用してPostgreSQLを使用するよ</p>
<p>サンプルサイトだよ</p>
{% endblock %}

リスト表示 book_list.html

book_list.html
<!-- templates/book_list.html -->

{% extends "base.html" %}
{% block title %}Books List{% endblock title %}
{% block content %}
<h1>書籍一覧</h1>
<ul>
    {% for book in object_list %}
    <li><a href="{% url 'book-detail' book.pk %}">{{ book.title }}</a> (著者:{{ book.author }})</li>
    {% endfor %}
</ul>
<a href="{% url 'book-create' %}">新規登録</a>
{% endblock %}

詳細画面 book_detail.html

book_detail.html
<!-- templates/book_detail.html -->

{% extends "base.html" %}
{% block title %}Book Detail{% endblock title %}
{% block content %}
<h1>{{ object.title }}</h1>
<p>著者: {{ object.author }}</p>
<p><a href="{% url 'book-update' book.pk %}">編集はこちら</a></p>
<p><a href="{% url 'book-delete' book.pk %}">削除する</a></p>
<p><a href="{% url 'book-list' %}">一覧へ戻る</a></p>
{% endblock %}

新規登録 book_form.html

book_form.html
<!-- templates/book_form.html -->

{% extends "base.html" %}
{% block title %}New Book{% endblock title %}
{% block content %}
<h1>新規登録</h1>
<form method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">登録</button>
</form>
<p><a href="{% url 'book-list' %}">一覧へ戻る</a></p>
{% endblock %}

編集 book_update.html

book_update.html
<!-- templates/book_update.html -->

{% extends "base.html" %}
{% block title %}Update Book{% endblock title %}
{% block content %}
<h1>編集</h1>
<form method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">更新</button>
</form>
<p><a href="{% url 'book-list' %}">一覧へ戻る</a></p>
{% endblock %}

削除 book_delete.html

book_delete.html
<!-- templates/book_delete.html -->

{% extends "base.html" %}
{% block title %}Delete Book{% endblock title %}

{% block content %}
<h1>削除確認</h1>
<p>"{{ object.title }}"を削除してもよろしいですか?</p>
<form method="post">
    {% csrf_token %}
    <button type="submit">削除</button>
</form>
<a href="{% url 'book-list' %}">一覧へ戻る</a>
{% endblock %}

settings.pyにtemplatesを追加します。

settings.py
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [BASE_DIR / 'templates'], # ここに「BASE_DIR / 'templates'」を追加
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

admin.pyにBookを追加します。

admin.py
# myapp/admin.py

from django.contrib import admin
from .models import Book # 追加

admin.site.register(Book) # 追加

管理者サイト用にスーパーユーザーも作成しましょう。

$ python manage.py createsuperuser

ここで必要事項を入力して、スーパーユーザーを作成しましょう。

動作確認とデータベース内の確認

実際に動かしてみて、PostgreSQLでデータ処理が行われているかどうか確認してみましょう。
まずはマイグレーションを行います。

$ python manage.py makemigrations

$ python manage.py migrate

続いてサーバーを起動します。

$ python manage.py runserver

最初にブラウザからlocalhost:8000/adminにアクセスします。
そこで管理者サイトにログインし、Bookモデルにデータを作成してみてください。
作成後、再度データベースに接続します。先ほど作成したmyuserでmydatabaseに接続してみましょう。

$ psql -h localhost -p 5432 -U myuser -d mydatabase

-hはホスト名で -pはポート番号を表します。
続いてテーブルとデータを確認してみましょう。

mydatabase=# \dt

入力すると下記が表示されると思います。

                  List of relations
 Schema |            Name            | Type  | Owner  
--------+----------------------------+-------+--------
 public | auth_group                 | table | myuser
 public | auth_group_permissions     | table | myuser
 public | auth_permission            | table | myuser
 public | auth_user                  | table | myuser
 public | auth_user_groups           | table | myuser
 public | auth_user_user_permissions | table | myuser
 public | django_admin_log           | table | myuser
 public | django_content_type        | table | myuser
 public | django_migrations          | table | myuser
 public | django_session             | table | myuser
 public | myapp_book                 | table | myuser

続いてテーブル内のデータを確認してみます。

mydatabase=> SELECT * FROM psqlapp_book;

SELECT文でmyapp_bookテーブルのデータを全て取得します。
下記の通りに表示されると思います。

 id |     title      |    author    
----+----------------+--------------
  1 | ドラゴンボール         | 鳥山 明

それでは他のCRUD処理も全て実行してみましょう。それで全てうまくいけば、オッケーです。ある程度動かしたら、ターミナルで接続しているデータベースの情報もリスト表示と合っているかなど確認してみるといいと思います。

最後に

最後までご覧いただきありがとうございます。今回はPostgreSQLをDjangoで使用してみました。結構色々つまづいたのですが、なんとかうまくいきました。SQL文なども登場することになりましたが、詳しい説明は省いております。何かございましたら、教えていただけると幸いです。またアドバイスなどもぜひお願いいたします。
これからも記事を投稿していきたいと思いますので、引き続きよろしくお願いいたします。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?