Python Django入門 初めの1歩からWEBアプリ作成までの流れ その9 FormView, CreateView, DetailView, ListViewまとめて

models.py

models.py
# Create your models here.
from django.db import models
import datetime
JST = datetime.timezone(datetime.timedelta(hours=9))

# Create your models here.
class SampleListModel(models.Model):
    title = models.CharField('タイトル',max_length=50)
    text = models.TextField('本文')
    url = models.URLField('URL', blank=True)
    created_at = models.DateTimeField('作成日', default=datetime.datetime.now(tz=JST))

    def __str__(self):
        return self.title

class SampleDetailModel(models.Model):
    name = models.CharField('名前',max_length=256)
    feature = models.TextField('特徴')
    list = models.ForeignKey(SampleListModel, on_delete=models.CASCADE, related_name='related_list')

    def __str__(self):
        return self.name

forms.py

forms.py
from .models import SampleListModel, SampleDetailModel
from django.db import models
from django import forms

class SampleListForm(forms.ModelForm):
    class Meta:
        model = SampleListModel
        fields = "__all__"

    def __init__(self, *args, **kwargs):
        for field in self.base_fields.values():
            field.widget.attrs["class"]="form-control"
        super().__init__(*args, **kwargs)

class SampleDetailForm(forms.ModelForm):
    class Meta:
        model = SampleDetailModel
        fields = "__all__"

    def __init__(self, *args, **kwargs):
        for field in self.base_fields.values():
            field.widget.attrs["class"]="form-control"
        super().__init__(*args, **kwargs)  

views.py

views.py
from django.shortcuts import render, get_object_or_404
from django.views.generic import CreateView, ListView, DetailView
from .models import SampleListModel, SampleDetailModel
from .forms import SampleListForm, SampleDetailForm
from django.urls import reverse, reverse_lazy

# Create your views here.
class SampleListCreate(CreateView):
    template_name = 'app/list_create.html'
    form_class = SampleListForm
    success_url = reverse_lazy('app:app/list')

class SampleDetailCreate(CreateView):
    template_name = 'app/detail_create.html'
    form_class = SampleDetailForm
    success_url = reverse_lazy('app:app/list')

class SampleList(ListView):
    model = SampleListModel
    context_object_name = "sample_list"
    template_name = 'app/list.html'

class SampleDetail(DetailView):
    model = SampleListModel
    context_object_name = "sample_detail"
    template_name = "app/detail.html"

pj/urls.py

pj/urls.py
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('app.urls')),
]

app/urls.py

app/urls.py
from django.contrib import admin
from django.urls import path
from . import views

app_name = 'app'

urlpatterns = [
    path('', views.SampleList.as_view(), name='app/list'),
    path('detail/<int:pk>', views.SampleDetail.as_view(), name='app/detail'),
    path('list_create', views.SampleListCreate.as_view(), name='app/list_create'),
    path('detail_create', views.SampleDetailCreate.as_view(), name='app/detail_create'),
]

settings.py

settings.py
"""
Django settings for pj project.

Generated by 'django-admin startproject' using Django 3.2.6.

For more information on this file, see

Django
The web framework for perfectionists with deadlines.
For the full list of settings and their values, see
Django
The web framework for perfectionists with deadlines.
""" from pathlib import Path # Build paths inside the project like this: BASE_DIR / 'subdir'. BASE_DIR = Path(__file__).resolve().parent.parent # Quick-start development settings - unsuitable for production # See https://docs.djangoproject.com/en/3.2/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = 'django-insecure-!f$ze!g_kk^w09n61tf$9h5+yrpbo7mccflq#jmb@1b1^$99eu' # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True ALLOWED_HOSTS = [] # Application definition INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'app', ] MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ] ROOT_URLCONF = 'pj.urls' TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [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', ], }, }, ] WSGI_APPLICATION = 'pj.wsgi.application' # Database # https://docs.djangoproject.com/en/3.2/ref/settings/#databases DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': BASE_DIR / 'db.sqlite3', } } # Password validation # https://docs.djangoproject.com/en/3.2/ref/settings/#auth-password-validators AUTH_PASSWORD_VALIDATORS = [ { 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', }, { 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', }, { 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', }, { 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', }, ] # Internationalization # https://docs.djangoproject.com/en/3.2/topics/i18n/ LANGUAGE_CODE = 'en-us' TIME_ZONE = 'UTC' USE_I18N = True USE_L10N = True USE_TZ = True # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/3.2/howto/static-files/ STATIC_URL = '/static/' import os STATICFILES_DIRS = ( os.path.join(BASE_DIR, "static/"), ) # Default primary key field type # https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'

pj/templates/app/base.html

pj/templates/app/base.html
{% load static %}
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Python Django CreateView, ListView, DetailView</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
    <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
    <link rel="stylesheet" href="{% static 'app/style.css' %}">
</head>
<body>
    <header class="page-header wrapper">
        <h1><a href="/"><img class="logo" src="images/logo_zeroterasu.png" alt="ZeroTerasuウェブサイト ホーム"><span> ZeroTerasu WebSite</span></a></h1>
        <nav class="page-nav">
            <ul class="main-nav">
                <li><a href="about.html">プロフィール</a></li>
                <li><a href="works.html">制作実績</a></li>
                <li><a href="https://zeroterasu.com/blog/">ブログ</a></li>
                <li><a href="contact.php">お問い合わせ</a></li>
            </ul>
        </nav>
    </header>
    {% block main %}
    {% endblock %}
    <footer>
        <div class="wrapper">
            <p><small>© 2021 ZeroTerasu</small></p>
            <a href="privacy_policy">プライバシーポリシー</a>
        </div>
    </footer>
</body>
</html>

pj/templates/app/list_create.html

pj/templates/app/list_create.html
{% extends 'app/base.html' %}
{% block main %}
<div class="container my-3">
    <div class="text-center my-3">
        <h2>新しいリストを作成</h2>
    </div>
    <form method="POST"> {% csrf_token %}
        {{ form.as_p }}
        <button class="btn btn-primary form-control" type="submit">登録</button>
    </form>
    <a href="{% url 'app:app/list' %}">リスト一覧ページ</a><br>
    <a href="{% url 'app:app/detail_create' %}">詳細作成ページ</a><br>
</div>
{% endblock %}

pj/templates/app/detail_create.html

pj/templates/app/detail_create.html
{% extends 'app/base.html' %}
{% block main %}
<div class="container my-3">
    <div class="text-center my-3">
        <h2>新しい詳細を作成</h2>
    </div>
    <form method="POST"> {% csrf_token %}
        {{ form.as_p }}
        <button class="btn btn-primary form-control" type="submit">登録</button>
    </form>
    <a href="{% url 'app:app/list' %}">リスト一覧ページ</a><br>
    <a href="{% url 'app:app/list_create' %}">リスト作成ページ</a><br>
</div>
{% endblock %}

pj/templates/app/list.html

pj/templates/app/list.html
{% extends 'app/base.html' %}
{% block main %}
<div class="wrapper">
    <h2>リスト一覧</h2>
    <table class="table">
        <thead>
          <tr>
            <th>リスト名</th>
            <th></th>
          </tr>
        </thead>
        <tbody>
          {% for sample in sample_list %}
          <tr>
            <td>{{ sample.title }}</td>
            <td><a href="detail/{{ sample.id }}">詳細</a></td>
          </tr>
          {% endfor %}
        </tbody>
      </table>
    <a href="{% url 'app:app/list_create' %}">リスト作成ページ</a><br>
    <a href="{% url 'app:app/detail_create' %}">詳細作成ページ</a><br>
</div>
{% endblock %}

pj/templates/app/detail.html

pj/templates/app/detail.html
{% extends 'app/base.html' %}
{% block main %}
<div class="wrapper">
    <h2>詳細ページ</h2>
    <h2>リスト詳細</h2>
    <table class="table">
      <thead>
        <tr>
          <th scope="col">リスト名</th>
          <th scope="col">本文</th>
          <th scope="col">URL</th>
      </tr>
    </thead>
      <tbody>
        <tr>
          <td>{{ sample_detail.title }}</td>
          <td>{{ sample_detail.text }}</td>
          <td>{{ sample_detail.url }}</td>
        </tr>
      <tbody>
    </table>
    <h3>詳細情報</h3><br>
    <table class="table">
        <thead>
          <tr>
            <th scope="col">name</th>
            <th scope="col">feature</th>
        </tr>
      </thead>
        <tbody>
    {% for detail in sample_detail.related_list.all %}
          <tr>
            <td>{{ detail.name }}</td>
            <td>{{ detail.feature }}</td>
          </tr>
    {% endfor %}
        <tbody>
    </table>
    <br>
    <a href="{% url 'app:app/list' %}">リスト一覧ページ</a><br>
    <a href="{% url 'app:app/list_create' %}">リスト作成ページ</a><br>
    <a href="{% url 'app:app/detail_create' %}">詳細作成ページ</a><br>
</div>
{% endblock %}

admin.py

admin.py
from django.contrib import admin
from .models import *

admin.site.register(SampleListModel)
admin.site.register(SampleDetailModel)

コメント

タイトルとURLをコピーしました