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)

About this article

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

This time, I'd like to create a super-simple diary application in Django. Also, this time, in order to deepen the understanding of how Django works, we will not use the class-based general-purpose view, but only create it with functions.

Deliverables

top page

Details page

Update page

Delete page

Advance preparation

First of all, from the environment construction. Create a project called Second and a Django app called diary. The project name is arbitrary, but it is safer to use only half-width alphanumeric characters if possible. If there are underscores or blank spaces in the project name, a mysterious error may occur in the procedure described below.

django-admin startproject Second
cd diary_project
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'

models.py This time, the process of registering data in Django's DB will occur, so define what kind of data will be put in the DB in models.py. Conversely, if you look at models.py, you can see what data fields are available in Django's DB. Also, if you do not explicitly set a primary key in models.py, a primary key called id will be set automatically.

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 called id is automatically registered.
    title = models.CharField('title', max_length=200)
    text = models.TextField('Text')
    date = models.DateField('date', default=timezone.now)

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 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
]

Register the URL in urls.py directly under the app. This time, we will create 5 pages of list, add, update, delete, and details. <int: pk> means the primary key associated with each article.

When I explained models.py, I wrote that the primary key called id was automatically registered, but In Django, it's customary to represent that id with a variable called pk. You can express it as <int: id>, but let's say <int: pk>.

For example, to access the detail page where pk is 1, it would be diary / detail / 1 /. Not required for list pages or additional pages that are not tied to a particular article.

forms.py 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. Originally, it's easy to write by using Django's divine feature called class-based generic views. Since this article is about writing with a function, I dare to write it with a function.

Second\diary\views.py


from django.shortcuts import render, redirect, get_object_or_404
from .forms import DayCreateForm
from .models import Day

def index(request):
    """
Display a list of diary
    """
    context = {
        'day_list':Day.objects.all(),
    }
    return render(request, 'diary/day_index.html', context)


def add(request):
    """
Added diary article
    """
    #Create a form based on the submitted content. If not POST, create an empty form.
    form = DayCreateForm(request.POST or None)

    # method==POST is when the send button is pressed. form.is_valid is True if there is no problem with the input contents.
    if request.method == 'POST' and form.is_valid():
        form.save()
        return redirect('diary:index')
    
    #If there is an error in the normal access or input contents, day again_form.Show html
    context = {
        'form':form
    }
    return render(request, 'diary/day_form.html', context)


def update(request, pk):
    """
Change diary article
    """
    #Get Day based on url pk (pk is the same as id)
    day = get_object_or_404(Day, pk=pk)

    #Associate the acquired Day with the form
    form = DayCreateForm(request.POST or None, instance=day)

    # method=POST(Press the send button), And if there is no problem with the input contents, save the form.
    if request.method == 'POST' and form.is_valid():
        form.save()
        return redirect('diary:index')
    
    #Display the first page if there is a problem with normal access or input contents
    context = {
        'form':form
    }
    return render(request, 'diary/day_form.html', context)


def delete(request, pk):
    """
Delete diary article
    """
    #Get Day based on the PK of the URL (pk is the same as id)
    day = get_object_or_404(Day, pk=pk)

    # method=POST(Press the send button)
    if request.method == 'POST':
        day.delete()
        return redirect('diary:index')
    
    #Normal access. Or access if there is a problem.
    context = {
        'day':day
    }
    return render(request, 'diary/day_delete.html', context)


def detail(request, pk):
    """
Diary detail page
    """
    #Get Day based on URL PK
    day = get_object_or_404(Day, pk=pk)

    context = {
        'day':day
    }
    return render(request, 'diary/day_detail.html', context)

def index (request): is a function to display a list of articles. Assign all the data of Day class in models.py to context. Using the render function, I am passing the created context to day_index.html.

def add (request): is a function for creating a new article. Create a form based on the submitted contents with form = DayCreateForm (request.POST or None). If it is in the state before submission, it will be an empty form. `ʻif request.method =='POST' and form.is_valid (): `` is the process when the submit button is pressed and there is no problem with the contents. Since there is no problem, save it with form.save () and redirect to the index.html page. In case of normal access or if there is an error in the input, pass the context to day_form.html with the render function.

def update (request, pk): is a function to change the content of the article. When viewing this update page, the URL will be diary / update /

. Since we need the primary key of the article to be updated, pass pk as an argument. Link the pk received by the URL to the Day class and get the content of the article with the following code. day = get_object_or_404(Day, pk=pk) The subsequent processing is the same flow as the add function.

def delete (request, pk): is a function to delete an article. It is almost the same process as update, but since it is deleted, there is no need to operate the form, so it is not created. Delete the article with day.delete () and redirect to index.html.

def detail (request, pk): is a function to display the detail page of the article. It's simple because you don't have to create a form either.

Creating an html file

Finally, create an html file. Create a templates folder under the diary folder, and then create a diary folder.

  • It is easier to remember / / templates / .

Creating base.html

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

  • CSS and JavaScript use Bootstrap.

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>

Creating day_index.html

It is a list page of articles.

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.

Second\diary\templates\diary\day_index.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 day_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>

{% endblock %}

Creating day_detail.html

This is the details page. 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_delete.html

Similar content continues, but this is the end. The last is the delete page.

Second\diary\templates\diary\day_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.

Recommended Posts

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 5 I made a super simple diary application with a class-based general-purpose view
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 3 I tried using the template file inheritance function
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 1 I tried to display an HTML page that only says "Hello World"
I made a simple book application with python + Flask ~ Introduction ~
[Introduction] I want to make a Mastodon Bot with Python! 【Beginners】
I tried to make a todo application using bottle with python
I made a WEB application with Django
I made a GUI application with Python + PyQt5
I tried to create a table only with Django
(Python) Try to develop a web application using Django
I made a package to filter time series with python
Easy-to-understand explanation of Python Web application (Django) even for beginners (5) [Introduction to DB operation with Django shell]
I made a library to easily read config files with Python
[Python] A memo to operate ROM created by GBDK with PyBoy
I tried to make a 2channel post notification application with Python
I made a poker game server chat-holdem using websocket with python
I made a Line-bot using Python!
I made a fortune with Python.
I made a daemon with 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
[Django] I made a field to enter the date with 4 digit numbers
Python beginners publish web applications using machine learning [Part 2] Introduction to explosive Python !!
[Streamlit] I hate JavaScript, so I make a web application only with Python
I want to make a web application using React and Python flask
Implement a simple application with Python full scratch without using a web framework.
Web application using Bottle (1)
Create Django Todo list
Create ToDo List [Python Django]
I tried to make a todo application using bottle 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