LoginSignup
5
11

More than 5 years have passed since last update.

Python + Django でCRUD

Last updated at Posted at 2018-12-13

Djangoでジェネリックビューを使ったCRUDです。

1.環境

カテゴリ バージョンなど
os windows 10 home 64bit
python 3.6.5
django 2.1.4

2.アプリケーションの作成

(1)以下のコマンドを実行してアプリケーションを作成する。

cmd.prompt
(venv) C:\data\python\myproject>python manage.py startapp employee

(2)ファイル構成

完成後は以下のようなフォルダ/ファイル構成になります。

employee
│  admin.py
│  apps.py
│  models.py
│  tests.py
│  urls.py
│  views.py
│  __init__.py
├─migrations
│  │  0001_initial.py
・・・
├─templates
│  └─employee
│          create.html
│          delete.html
│          detail.html
│          index.html
│          update.html

3.migrate

まずはmodelを永続化するために、modelを作成してmigrateしていきます。

(1)models.pyを編集する。

employee\models.py
from django.db import models
from django.urls import reverse

# Create your models here.
class Employee(models.Model):
    """従業員"""
    name = models.CharField('氏名', max_length=255)
    age = models.IntegerField('年齢', blank=True, default=0)
    birthday = models.DateField('誕生日', blank=True)
    hiredate = models.DateField('入社日', blank=True)
    retiredate = models.DateField('退社日', blank=True)
    createddate = models.DateTimeField('登録日時', auto_now_add=True)
    lastmodifieddate = models.DateTimeField('最終更新日時', auto_now=True)

    def __str__(self):
        return self.name

    def get_absolute_url(self):
        """
        更処理完了時の戻り先URL
        """
        return reverse('employee:index')

(2)プロジェクトにアプリケーションを追加する。

  • settings.py

INSTALLED_APPSに以下のように追加します。

myproject\settings.py
INSTALLED_APPS = [
    'accounts.apps.AccountsConfig', 
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
・・・
    'bootstrap4', #追加
    'employee', #追加
]

bootstrap4はこの記事を参考にしてください。

  • urls.py

myprojectのurls.pyの「urlpatterns 」にも追加しておきます。

myproject\urls.py
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
・・・
    path('employee/', include('employee.urls')),   # ←ここを追加
    path('admin/', admin.site.urls),
]

(3)migrate

modelをmigrateします。

cmd.prompt
(venv) C:\data\python\myproject>manage.py makemigrations employee
・・
(venv) C:\data\python\myproject>manage.py migrate employee

4.crudの実装

準備ができましたのでいよいよ実装していきます。

(1)urls.py

最初にルーティング(urls.py)です。CRUDは「create, read, update, delete」という意味で、それぞれのURLを設定しておきます。ただ、readは、一覧表示と詳細表示の2つがあるので、readとせず、それぞれindex, detailとしています。

employee\urls.py
from django.urls import path
from . import views

app_name = 'employee'
urlpatterns = [
    path('', views.IndexView.as_view(), name='index'), 
    path('employee/create/', views.CreateView.as_view(), name='create'),
    path('employee/<int:pk>/', views.DetailView.as_view(), name='detail'),
    path('employee/<int:pk>/update/', views.UpdateView.as_view(), name='update'),
    path('employee/<int:pk>/delete/', views.DeleteView.as_view(), name='delete'),
]

(2)views.py

viewには、ジェネリックビュー()を使います。

employee\views.py
from django.urls import reverse_lazy
from django.views import generic
from .models import Employee
from pure_pagination.mixins import PaginationMixin

class IndexView(PaginationMixin, generic.ListView):
    model = Employee
    paginate_by = 5
    ordering = ['-createddate']
    template_name = 'employee/index.html'

class DetailView(generic.DetailView):
    model = Employee
    fields = '__all__'  # or ['colmunname', 'colmunname', 'colmunname']
    template_name = 'employee/detail.html'

class CreateView(generic.edit.CreateView):
    model = Employee
    fields = '__all__'  # or ['colmunname', 'colmunname', 'colmunname']
    template_name = 'employee/create.html'

class UpdateView(generic.edit.UpdateView):
    model = Employee
    fields = '__all__'  # or ['colmunname', 'colmunname', 'colmunname']
    template_name = 'employee/update.html'

class DeleteView(generic.edit.DeleteView):
    model = Employee
    success_url = reverse_lazy('employee:index')
    template_name = 'employee/delete.html'

(3)html

最後はhtmlです。

employee\templates\employee\create.html
{% extends 'commons/base.html' %}

{% load static %}

{% block links %}
<style media="screen">
</style>
{% endblock %}

{% block headertitle %}
新規作成
{% endblock %}

{% block content %}
  <form action="" method="post">
      {% csrf_token %}
      <table>{{form.as_table}}</table>
      <button type="submit" class="submit btn btn-info">登録</button>
  </form>
{% endblock %}
employee\templates\employee\update.html
{% extends 'commons/base.html' %}

{% load static %}

{% block links %}
<style media="screen">
</style>
{% endblock %}

{% block headertitle %}
変更
{% endblock %}

{% block content %}
  <form action="" method="post">
      {% csrf_token %}
      <table>{{form.as_table}}</table>
      <button type="submit" class="submit btn btn-info">登録</button>
  </form>
{% endblock %}
employee\templates\employee\delete.html
{% extends 'commons/base.html' %}

{% load static %}

{% block links %}
<style media="screen">
</style>
{% endblock %}

{% block headertitle %}
削除
{% endblock %}

{% block content %}
  <form action="" method="post">
    {% csrf_token %}
    <table>
        <tr><td>氏名     :</td><td>{{ object.name             }}</td></tr>
        <tr><td>年齢     :</td><td>{{ object.age              }}</td></tr>
        <tr><td>生年月日 :</td><td>{{ object.birthday         }}</td></tr>
        <tr><td>入社日   :</td><td>{{ object.hiredate         }}</td></tr>
        <tr><td>退社日   :</td><td>{{ object.retiredate       }}</td></tr>
        <tr><td>登録日時 :</td><td>{{ object.createddate      }}</td></tr>
        <tr><td>更新日時 :</td><td>{{ object.lastmodifieddate }}</td></tr>
        <br/>
    </table>
    <br/>
    <br/>
    <button type="submit" class="submit delete btn btn-danger">削除</button>
  </form>
{% endblock %}
employee\templates\employee\detail.html
{% extends 'commons/subwinbase.html' %}

{% load static %}

{% block links %}
<style media="screen">
  td{
    padding:5px;
  }
</style>
{% endblock %}

{% block headertitle %}
詳細表示
{% endblock %}

{% block content %}
  <div>
    <table>
        <tr><td>氏名     </td><td>{{ object.name             }}</td></tr>
        <tr><td>年齢     </td><td>{{ object.age              }}</td></tr>
        <tr><td>生年月日 </td><td>{{ object.birthday         }}</td></tr>
        <tr><td>入社日   </td><td>{{ object.hiredate         }}</td></tr>
        <tr><td>退社日   </td><td>{{ object.retiredate       }}</td></tr>
        <tr><td>登録日時 </td><td>{{ object.createddate      }}</td></tr>
        <tr><td>更新日時 </td><td>{{ object.lastmodifieddate }}</td></tr>
    </table>
    <br/>
  </div>
{% endblock %}
employee\templates\employee\index.html
{% extends 'commons/subwinbase.html' %}

{% load static %}

{% block links %}
<link href="{% static 'css/pagination.css' %}" rel="stylesheet">
<style media="screen">
  .pagination > div {
    display: inline-block;
  }
</style>
{% endblock %}

{% block headertitle %}
一覧
{% endblock %}

{% block content %}

  <table class="table table-striped table-bordered table-sm">
    <thead>
      <tr>
        <th>ID</th>
        <th>氏名</th>
        <th>年齢</th>
        <th>生年月日</th>
        <th>入社年月日</th>
        <th>退職年月日</th>
        <th><a href="{% url 'employee:create' %}" class="btn btn-primary btn-sm">追加</a></th>
      </tr>
    </thead>
    <tbody>
      {% for employee in object_list %}
      <tr>
        <td>{{ employee.id }}</td>
        <td>{{ employee.name }}</td>
        <td>{{ employee.age }}</td>
        <td>{{ employee.birthday }}</td>
        <td>{{ employee.hiredate }}</td>
        <td>{{ employee.retiredate }}</td>
        <td>
          <a href="{% url 'employee:update' employee.pk %}" class="btn btn-info btn-sm">修正</a>
          <a href="{% url 'employee:delete' employee.pk %}" class="btn btn-danger btn-sm">削除</a>
          <a href="{% url 'employee:detail' employee.pk %}" onclick="OpenSubWin(this);return false;" class="btn btn-success btn-sm">照会</a>
        </td>
      </tr>
      {% endfor %}
    </tbody>
  </table>

  <br/>
  <!-- pagination -->
  {% include 'commons\pagination2.html' %}
{% endblock %}

base.html、pagination2.htmlはそれぞれ以下の記事を参照。
Python+Django+psycopg2で内部結合クエリを試す
DjangoでPaginationを実装する

以上で実装が完了
※本番ではformを作成して入力項目のバリデーションなども実装が必要でしょうが、この記事ではここまでとします。

5.完成イメージ

あとはデータを入力して動かしてみましょう。

image.png

image.png

わずかなコードでCRUDが実装できます。

以上です。

追記 2018.12.14

detail.htmlで使用しているjavascript「OpenSubWin」はこちらを参照ください。

ブラウザを閉じるときに、親画面が開いた子画面(サブウィンドウ)を閉じる

5
11
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
5
11