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.
top page
Details page
Update page
Delete page
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
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.
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">«</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">»</span>
</a>
</li>
{% endif %}
</ul>
</nav>
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 %}
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 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 %}
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 %}
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