A super introduction to Django by Python beginners! Part 5 I made a super simple diary application with a class-based general-purpose view

About this article

This is the output page of the result of learning about Django on Udemy. The previous article is here .

This time, using the class-based general-purpose view, I want to create a super simple diary application in Django. Class-based generic views make the notation of views.py very easy.

Deliverables

top page

Details page

Update page

Delete page

Advance preparation

First of all, from the environment construction. It is the same as the previous article, but I will describe it just in case. Create a project called Second and a Django app called diary.

django-admin startproject Second
cd Second
py .\manage.py startapp diary

Register the diary app in settings.py and set Japan time

Second\Second\sattings.py


INSTALLED_APPS = [
    'diary',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

LANGUAGE_CODE = 'ja'

TIME_ZONE = 'Asia/Tokyo'

admin.py Account settings for the administrator and settings for the management screen. This time it is unnecessary because there is no login function, but I will only describe how to do it.

py manage.py createsuperuser #Command to create administrator user

Add admin.py as below.

Second\Second\admin.py


from django.contrib import admin
from .models import Day

admin.site.register(Day)

models.py models.py is almost the same as the previous article. Add def __str __ (self): to make it easier to understand when browsing on the admin site. By adding this, it will be the character string notation of the title when browsing the data registered in the Day model on the admin site.

Second\Second\models.py


from django.db import models
from django.utils import timezone

class Day(models.Model):
    #I haven't declared it here, but the primary key pk is automatically registered.
    title = models.CharField('title', max_length=200)
    text = models.TextField('Text')
    date = models.DateField('date', default=timezone.now)

    def __str__(self):
        return self.title

After inputting models.py, register it in the DB with manage.py. Move to the folder where manage.py is saved and register it with the following command.

py .\manage.py makemigrations
py .\manage.py migrate

When you run makemigrations, you may get a RecursionError. RecursionError: maximum recursion depth exceeded while calling a Python object

One of the causes of the error is that the project name contains characters other than half-width alphanumeric characters. This can happen if the path contains blank spaces. Please note that blank spaces may be included in the path if saved in a special folder such as OneDirve.

urls.py It is the same as the previous article, but I will describe it just in case. In urls.py directly under the project, set to go to urls.py directly under the app.

Second\Second\urls.py


from django.contrib import admin
from django.urls import path, include

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

Enter urls.py directly under the app as follows.

Second\diary\urls.py


from django.urls import path
from . import views

app_name = 'diary'

urlpatterns = [
    path('', views.index, name='index'), #List page
    path('add/', views.add, name='add'), #Additional page
    path('update/<int:pk>/', views.update, name='update'), #Update page
    path('delete/<int:pk>', views.delete, name='delete'), #Delete page
    path('detail/<int:pk>', views.detail, name='detail'), #Details page
]

forms.py It is the same as the previous article, but I will describe it just in case. Before creating views.py, create a new file called forms.py. Create a file called forms.py in the same folder as views.py (Second \ diary) Please make the contents as follows.

Second\diary\forms.py


from django import forms
from .models import Day


class DayCreateForm(forms.ModelForm):

    class Meta:
        model = Day
        fields = '__all__'

Of course, when creating or updating an article, an input field is required in the HTML file. In order to create the input field, it is necessary to configure a Form in the HTML file.

It is this forms.py that defines what data to pass to that Form. This time, let's pass all the data of the Day class defined in models.py. If you want to pass everything, set fields ='__ all__'.

The class name DayCreateForm is arbitrary, The class Meta in it is a fixed phrase. Let's not change it.

views.py Create a function to display the list, add, update, delete, and detail pages in views.py. Last time I dared to fill it out with a function, but Django has a divine feature called a class-based generic view. This divine feature makes it very easy to fill out.

Second\diary\views.py


from django.shortcuts import render, redirect, get_object_or_404
from .forms import DayCreateForm
from .models import Day
from django.views import generic
from django.urls import reverse_lazy

class IndexView(generic.ListView):
    model = Day
    paginate_by = 3

class DayCreateView(generic.CreateView):
    model = Day
    form_class = DayCreateForm
    success_url = reverse_lazy('diary:index')

class DayUpdateView(generic.UpdateView):
    #It has almost the same contents as CreateView, but passes not only form but also Day object.
    model = Day
    form_class = DayCreateForm
    success_url = reverse_lazy('diary:index')

class DayDeleteView(generic.DeleteView):
    model = Day
    success_url = reverse_lazy('diary:index')

class DayDetailView(generic.DetailView):
    model = Day

Creating an html file

Finally, create an html file. This is almost the same as last time, but there is one difference from the last time. That is, the template file name is defined as standard.

Specifically, in the template file that uses the ListView class, The file name <app name> _list.html is registered as standard. With DetailView, <app name> _detail.html With DeleteView, <app name> _confirm_delete.html It is possible to register a template file with a non-standard name, It may be safer to register with a standard name to make it easier for others to see.

Creating base.html

First, create base.html. This is the html file that is the masterpiece of everything.

Link the list page and new article creation in the nav part. Link with {% url'<app name>: <name value defined in urls.py>'%}.

Second\diary\templates\diary\base.html


<!doctype html>
<html lang="ja">
  <head>
    <title>Diary application</title>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css" integrity="sha384-PsH8R72JQ3SOdhVi3uxftmaW6Vc51MKb0q5P2rRUpPvrszuE4W1povHYgTpBfshb" crossorigin="anonymous">
  </head>
  <body>

    <div class="container">
      <nav class="nav">
        <a class="nav-link active" href="{% url 'diary:index' %}">List</a>
        <a class="nav-link" href="{% url 'diary:add' %}">add to</a>
      </nav>
      {% block content %}
      {% endblock %}
    </div>

    <!-- Optional JavaScript -->
    <!-- jQuery first, then Popper.js, then Bootstrap JS -->
    <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.3/umd/popper.min.js" integrity="sha384-vFJXuSJphROIrBnz7yo7oB41mKfc8JzQZiCq4NCceLEaO4IHwicKwpJf9c9IpFgh" crossorigin="anonymous"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/js/bootstrap.min.js" integrity="sha384-alpBpkh1PFOepccYVYDB4do5UnbKysX5WZXm3XxPqe5iKTfUKjNkCk9SaVuEZflJ" crossorigin="anonymous"></script>
  </body>
</html>

page.html This time we will add a pagination function. Save it in the template folder with the file name page.html and write as follows.

Second\diary\templates\diary\page.html


<nav aria-label="Page navigation">
  <ul class="pagination">
 
      {% if page_obj.has_previous %}
        <li class="page-item">
        <a class="page-link" href="?page={{ page_obj.previous_page_number }}">
          <span aria-hidden="true">&laquo;</span>
        </a>
      </li>
      {% endif %}
    
      {% for link_page in page_obj.paginator.page_range %}
        {% if link_page == page_obj.number %}
          <li class="page-item active">
            <a class="page-link" href="?page={{ link_page }}">
              {{ link_page }}
            </a>
          </li>
        {% else %}
          <li class="page-item">
            <a class="page-link" href="?page={{ link_page }}">
              {{ link_page }}
            </a>
          </li>
        {% endif %}
      {% endfor %}
    
      {% if page_obj.has_next %}
        <li class="page-item">
        <a class="page-link" href="?page={{ page_obj.next_page_number }}" aria-label="Next">
          <span aria-hidden="true">&raquo;</span>
        </a>
      </li>
      {% endif %}
    
  </ul>
</nav>

Creating day_list.html

It is a list page of articles. In the previous article, the file name was day_index, This time we are using the ListView class, so Register with the file name day_list.html.

From views.py, day_list is passed the context of Key, so You can use day_list to access the article titles and dates stored in the DB. This is displayed using a for statement.

It is a mechanism to access the update page of each article by passing day.pk to update and delete.

Finally, include the pagination feature with {% include'diary / page.html%}.

Second\diary\templates\diary\day_list.html


{% extends 'diary/base.html' %}

{% block content %}

<h1>Diary list</h1>

<table class="table">
    <thead>
        <tr>
            <th>title</th>
            <th>date</th>
            <th>Update process</th>
            <th>Delete process</th>
        </tr>
    </thead>
    <tbody>
    {% for day in object_list %}
        <tr>
            <td><a href="{% url 'diary:detail' day.pk %}">{{ day.title }}</a></td>
            <td>{{ day.date }}</td>
            <td><a href="{% url 'diary:update' day.pk %}">update</a></td>
            <td><a href="{% url 'diary:delete' day.pk %}">Delete</a></td>
        </tr>
    {% endfor %}
    </tbody>
</table>

{% include 'diary/page.html' %}

{% endblock %}

Creating day_detail.html

This is the details page. Since we are using the DetailView class, save it as day_detail.html.

The title, text and date are displayed. After the text, the line breaksbr is added This is to express line breaks on HTML. There is no problem without it.

Second\diary\templates\diary\day_detail.html.html


{% extends 'diary/base.html' %}
{% block content %}
    <table class="table">
        <tr>
            <th>title</th>
            <td>{{ day.title }}</td>
        </tr>
        <tr>
            <th>Text</th>
            <td>{{ day.text | linebreaksbr}}</td>
        </tr>
        <tr>
            <th>date</th>
            <td>{{ day.date }}</td>
        </tr>
    </table>
    <a href="{% url 'diary:update' day.pk %}"><button class="btn btn-primary">update</button></a>
    <a href="{% url 'diary:delete' day.pk %}"><button class="btn btn-danger">Delete</button></a>    
    
{% endblock %}

Creating day_form.html

Creating a form. It is used for creating and updating articles.

Second\diary\templates\diary\day_form.html


{% extends 'diary/base.html' %}

{% block content %}
<form action="" method="POST">
    <table class="tabel">
        <tr>
            <th>title</th>
            <td>{{ form.title }}</td>
        </tr>
        <tr>
            <th>Text</th>
            <td>{{ form.text }}</td>
        </tr>
        <tr>
            <th>date</th>
            <td>{{ form.date }}</td>
        </tr>
    </table>

    <button type="submit" class="btn btn-primary">Send</button>
    {% csrf_token %}
</form>
{% endblock %}

Create day_confirm_delete.html

This is the delete page. Since we are using DeleteView Set it to the name day_confirm_delete.html.

Second\diary\templates\diary\day_confirm_delete.html


{% extends 'diary/base.html' %}
{% block content %}
<form action="" method="POST">
    <table class="table">
        <tr>
            <th>title</th>
            <td>{{ day.title }}</td>
        </tr>
        <tr>
            <th>Text</th>
            <td>{{ day.text }}</td>
        </tr>
        <tr>
            <th>date</th>
            <td>{{ day.date }}</td>
        </tr>
    </table>
    <p>Delete this data.</p>
    <button type="submit" class="btn btn-primary">Delete</button>
    {% csrf_token %}
</form>
{% endblock %}

Operation check

After that, let's check the operation with py manage.py run server. If you can create / update / delete an article, you are successful. Also, make sure that the pagination feature is enabled.

Recommended Posts

A super introduction to Django by Python beginners! Part 5 I made a super simple diary application with a class-based general-purpose view
A super introduction to Django by Python beginners! Part 4 I made a super-simple diary application (created only with functions without using a class-based general-purpose view)
A super introduction to Django by Python beginners! Part 6 I tried to implement the login function
A super introduction to Django by Python beginners! Part 3 I tried using the template file inheritance function
I made a simple book application with python + Flask ~ Introduction ~
A super introduction to Django by Python beginners! Part 2 I tried using the convenient functions of the template
A super introduction to Django by Python beginners! Part 1 I tried to display an HTML page that only says "Hello World"
[Introduction] I want to make a Mastodon Bot with Python! 【Beginners】
I made a simple blackjack with Python
I made a WEB application with Django
I tried to discriminate a 6-digit number with a number discrimination application made with python
I made a GUI application with Python + PyQt5
Web application made with Python3.4 + Django (Part.1 Environment construction)
I made a simple typing game with tkinter in Python
I made a package to filter time series with python
I made a class to get the analysis result by MeCab in ndarray with python
I made a fortune with Python.
I made a daemon with Python
I made a simple circuit with Python (AND, OR, NOR, etc.)
I made a library to easily read config files with Python
[Python] I made an image viewer with a simple sorting function.
I tried to make a 2channel post notification application with Python
I tried to make a todo application using bottle with python
Easy-to-understand explanation of Python Web application (Django) even for beginners (5) [Introduction to DB operation with Django shell]
A simple RSS reader made with Django
I tried to communicate with a remote server by Socket communication with Python.
I made a tool to automatically browse multiple sites with Selenium (Python)
[Introduction to Udemy Python3 + Application] 47. Process the dictionary with a for statement
I made a web application in Python that converts Markdown to HTML
A super introduction to Python bit operations
I made a character counter with Python
[Django] I made a field to enter the date with 4 digit numbers
I made a Hex map with Python
I made a roguelike game with Python
I made a configuration file with Python
A textbook for beginners made by Python beginners
I made a neuron simulator with Python
Introduction to AI creation with Python! Part 3 I tried to classify and predict images with a convolutional neural network (CNN)
Introduction to AI creation with Python! Part 2 I tried to predict the house price in Boston with a neural network
[ES Lab] I tried to develop a WEB application with Python and Flask ②
I made a module in C language to filter images loaded by Python
A story that I was addicted to when I made SFTP communication with python
I made a competitive programming glossary with Python
I made a weather forecast bot-like with Python.
I made a Twitter fujoshi blocker with Python ①
I want to make a game with Python
[Python] I made a Youtube Downloader with Tkinter.
I made a simple Bitcoin wallet with pycoin
A simple to-do list created with Python + Django
[Introduction to Udemy Python3 + Application] 9. First, print with print
I want to write to a file with Python
I made a bin picking game with Python
I made a Mattermost bot with Python (+ Flask)
I made a program to convert images into ASCII art with Python and OpenCV
[Mac] I want to make a simple HTTP server that runs CGI with Python
How to publish GitHub Pages with Pelican, a static HTML generator made by Python
[Introduction to system trading] I drew a Stochastic Oscillator with python and played with it ♬
I can't sleep until I build a server !! (Introduction to Python server made in one day)
I made a Twitter BOT with GAE (python) (with a reference)
I tried to create a table only with Django
I made a Christmas tree lighting game with Python