This article is the last day of Django Advent Calendar 2020.
Nice to meet you.
I usually use Django to develop web apps.
This time has come this year as well. By the way, I posted on the same day last year.
This year's Django Advent Calendar 2020 is also great and has lots of practical articles. I enjoyed seeing you.
Personally, I think the beauty of Django is that you can make ** "easy" ** applications ** "easily" **. So, in this article, I'd like to describe the process of creating a simple and basic ** Django application, along with ** code.
I hope this article has contributed to the further spread of Django.
-Preparation -Create Application -Create Model -Create View -Create Template --Routing Definition -Completed
First, let's do ** simple preparations ** before building the application.
Install django. Execute the following command from the terminal for Linux OS and Mac, or from the command prompt for Windows.
python
$ pip install django
Collecting django
Downloading https://files.pythonhosted.org/packages/08/c7/7ce40e5a5cb47ede081b9fa8a3dd93d101c884882ae34927967b0792f5fb/Django-3.1.4-py3-none-any.whl (7.8MB)
|████████████████████████████████| 7.8MB 2.1MB/s
Requirement already satisfied: pytz in /Users/rinego/.pyenv/versions/3.8.3/lib/python3.8/site-packages (from django) (2019.3)
Collecting asgiref<4,>=3.2.10 (from django)
Downloading https://files.pythonhosted.org/packages/89/49/5531992efc62f9c6d08a7199dc31176c8c60f7b2548c6ef245f96f29d0d9/asgiref-3.3.1-py3-none-any.whl
Collecting sqlparse>=0.2.2 (from django)
Downloading https://files.pythonhosted.org/packages/14/05/6e8eb62ca685b10e34051a80d7ea94b7137369d8c0be5c3b9d9b6e3f5dae/sqlparse-0.4.1-py3-none-any.whl (42kB)
|████████████████████████████████| 51kB 3.5MB/s
Installing collected packages: asgiref, sqlparse, django
Successfully installed asgiref-3.3.1 django-3.1.4 sqlparse-0.4.1
Create a django project with the following command.
python
$ django-admin startproject my_project
When you execute the command, the following files will be created.
my_project/
manage.py
my_project/
__init__.py
asgi.py
settings.py
urls.py
wsgi.py
Move to the my_project
directory on the first level and make various settings after that.
python
$ cd my_project
Django's settings are defined in my_project/my_project/settings.py
.
You don't have to change the database settings unless you are particular about it. It is a standard and nice setting.
Let's leave only ** language and time zone ** in Japan.
my_project/my_project/settings.py
# LANGUAGE_CODE = 'en-us'
LANGUAGE_CODE = 'ja'
# TIME_ZONE = 'UTC'
TIME_ZONE = 'Asia/Tokyo'
First, migrate your database to create a database managed by Django.
python
$ python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying admin.0002_logentry_remove_auto_add... OK
Applying admin.0003_logentry_add_action_flag_choices... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying auth.0007_alter_validators_add_error_messages... OK
Applying auth.0008_alter_user_username_max_length... OK
Applying auth.0009_alter_user_last_name_max_length... OK
Applying auth.0010_alter_group_name_max_length... OK
Applying auth.0011_update_proxy_permissions... OK
Applying auth.0012_alter_user_first_name_max_length... OK
Applying sessions.0001_initial... OK
Running the command will create a file called my_project/db.sqlite3
.
Let's also create ** super user ** (administrator of the app to be created) at this timing.
python
$ python manage.py createsuperuser
Username (leave blank to use 'hoge'): admin
Email address: [email protected]
Password: XXXXX
Password (again): XXXXX
Superuser created successfully.
You will be asked the following items.
Make sure you don't forget the Username`` Password
, as you will use it later.
If you enter a simple one for Password
, you will be asked" Is it common but good? ".
python
This password is too common.
Bypass password validation and create user anyway? [y/N]:
It doesn't matter if the email address is appropriate.
Once you've done this, let's start the ** development server ** once.
Start the development server with the command python manage.py runserver
.
python
$ python manage.py runserver
Watching for file changes with StatReloader
Performing system checks...
System check identified no issues (0 silenced).
December 18, 2020 - 08:54:54
Django version 3.1.4, using settings 'my_project.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
In this state, try accessing http://127.0.0.1:8000/
with a browser.
It is OK if the following screen is displayed.
Quit the developer server with control + c
.
If you can do so far, you should have built the necessary environment for the time being, so all you have to do is write the code.
Now let's create an application.
This time, let's create an application that can ** create, edit, browse, and delete simple data **.
It's just like the toy app in ruby on rails tutorial.
In addition, Django has adopted the ** MTV model design concept **. It's not difficult at all, it's a replacement for each MVC model with a common design pattern.
The application is completed by defining Model, Template and View. (The name View is the most confusing ...)
First, let's create an application.
python
python manage.py startapp sample_app
When you execute the command, it should have the following hierarchical structure.
python
my_project/
manage.py
my_project/
__init__.py
asgi.py
settings.py
urls.py
wsgi.py
sample_app/
__init__.py
admin.py
apps.py
migrations
models.py
tests.py
views.py
In Django, under the project directory my_project /
,
The project setting my_project/my_project /
and the application directory my_project/sample_app /
are linked.
After creating the application, let's register it in the project. If you do not do this, the application will not be recognized by the project.
If you open my_project/sample_app/apps.py
, you will find a class called SampleAppConfig
.
Add this to INSTALLED_APPS
in my_project/my_project/settings.py
with the string *'sample_app.apps.SampleAppConfig', *.
my_project/my_project/settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'sample_app.apps.SampleAppConfig', # Add
]
Now you have created the application for the time being. From the next, we will actually create various parts of the application.
First, let's create a ** Model (database definition) **.
Define the data model of the application you want to create in my_project/sample_app/models.py
.
my_project/sample_app/models.py
from django.db import models
class Post(models.Model):
name = models.CharField('user name', max_length=15)
micropost = models.CharField('tweet', max_length=140, blank=True)
def __str__(self):
return self.name
In this way you can define the data structure of the application you want to create.
By the way, user name
and tweet
are arbitrary strings.
Give it a name that will help you identify what data you intended to define later.
Once you have created a model, you need to activate it.
Create a migrate file to reflect the changes in my_project/sample_app/models.py
with the following command.
python
$ python manage.py makemigrations sample_app
Migrations for 'sample_app':
sample_app/migrations/0001_initial.py
- Create model Post
Now that the migrate file is created, reflect it in the database with the following command.
python
$ python manage.py migrate sample_app
Operations to perform:
Apply all migrations: sample_app
Running migrations:
Applying sample_app.0001_initial... OK
This completes the model creation.
Next, create a ** View (process definition) **.
In my_project/sample_app/views.py
, define each function of" Create "," Modify "," List ", and" Delete "with a function.
my_project/sample_app/views.py
from django.shortcuts import render, get_object_or_404, redirect
from django.forms import ModelForm
from sample_app.models import Post
def create_post(request):
"""
Create new data
"""
#Create a new object
post = Post()
#When loading a page
if request.method == 'GET':
#Create form with newly created object
form = PostForm(instance=post)
#Pass form to Template when loading page
return render(request,
'sample_app/post_form.html', #Template to call
{'form': form}) #Data to pass to Template
#When the execute button is pressed
if request.method == 'POST':
#Create form with POSTed data
form = PostForm(request.POST, instance=post)
#Validation of input data
if form.is_valid():
#If there is no problem with the check result, create data
post = form.save(commit=False)
post.save()
return redirect('sample_app:read_post')
def read_post(request):
"""
Display a list of data
"""
#Get all objects
posts = Post.objects.all().order_by('id')
return render(request,
'sample_app/post_list.html', #Template to call
{'posts': posts}) #Data to pass to Template
def edit_post(request, post_id):
"""
Edit the target data
"""
#Get the target object with ID as an argument
post = get_object_or_404(Post, pk=post_id)
#When loading a page
if request.method == 'GET':
#Create form by target object
form = PostForm(instance=post)
#Pass form and data ID to Template when loading page
return render(request,
'sample_app/post_form.html', #Template to call
{'form': form, 'post_id': post_id}) #Data to pass to Template
#When the execute button is pressed
elif request.method == 'POST':
#Create form with POSTed data
form = PostForm(request.POST, instance=post)
#Validation of input data
if form.is_valid():
#If there is no problem with the check result, update the data
post = form.save(commit=False)
post.save()
#When the execute button is pressed, the process is executed and then redirected to the list screen.
return redirect('sample_app:read_post')
def delete_post(request, post_id):
#Get the target object
post = get_object_or_404(Post, pk=post_id)
post.delete()
#At the time of deletion request, redirect to the list display screen after executing deletion
return redirect('sample_app:read_post')
class PostForm(ModelForm):
"""
Form definition
"""
class Meta:
model = Post
#fields is models.Variable name defined in py
fields = ('name', 'micropost')
To briefly explain, it is as follows. (If you can see the code, you can skip it.)
create_post()
This function is called the data creation process.
The process when the page is loaded or when the execute button is pressed is branched by request.method
.
When the page loads, a new Post
object is used to generate the form.
Form definition is defined separately in class.
You can easily implement a form using the standard Django ModelForm
.
When the execute button is pressed, the Post object is created using the value entered in the form.
This is creating new data.
We also validate the input data.
This is also easy to implement using the standard Django feature form.is_valid
.
After the creation process, it is skipped to the data list screen.
read_post() This function is called as a process to display a data list. All you have to do is fetch all the data from the database and pass it directly to the Template.
edit_post()
This function is called data editing process.
Similar to the creation process, but it gets a Post
object and creates a form with the id passed as an argument.
The get_object_or_404
used in the function is a very useful standard Django feature.
It is a function to get an object, but if there is no target object, it will send a 404Error.
This will prevent you from inadvertently issuing a Server Error (500).
The process when the execute button is pressed is the same as Data creation process.
delete_post()
This function is called the data deletion process.
The Post
object is fetched and the target object is deleted by the id passed as an argument.
The deletion process does not pass data to Template, and redirects to the data list screen after executing the process.
By defining each process in View in this way, application functions can be implemented.
Next, create a ** Template (definition of display) **.
Template defines the screen display. After all, it's an html file.
Django has a fixed location for Templates.
Create a two-level directory under my_project/sample_app /
Prepare a directory called my_project/sample_app/templates/sample_app /
.
Here, we will create a Template to be used in the application.
This time, you need the following two templates.
-** Data list screen ** -** Data entry form screen **
Create my_project/sample_app/templates/sample_app/post_list.html
.
post_list.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Post lists</title>
</head>
<body>
<table>
<thead>
<tr>
<th>ID</th>
<th>User Name</th>
<th>Post</th>
</tr>
</thead>
<tbody>
{% for post in posts %}
<tr>
<th>{{ post.id }}</th>
<td>{{ post.name }}</td>
<td>{{ post.micropost }}</td>
<td>
<a href="{% url 'sample_app:edit_post' post_id=post.id %}">Fix</a>
<a href="{% url 'sample_app:delete_post' post_id=post.id %}">Delete</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<a href="{% url 'sample_app:create_post' %}">Create</a>
</body>
</html>
This Template is called from View's read_post ()
.
The important parts are as follows.
<tbody>
{% for post in posts %}
<tr>
<th>{{ post.id }}</th>
<td>{{ post.name }}</td>
<td>{{ post.micropost }}</td>
<td>
<a href="{% url 'sample_app:edit_post' post_id=post.id %}">Fix</a>
<a href="{% url 'sample_app:delete_post' post_id=post.id %}">Delete</a>
</td>
</tr>
{% endfor %}
</tbody>
We are now looping through the posts
received from View.
This is displaying as many table rows as there are data.
Create my_project/sample_app/templates/sample_app/post_form.html
.
post_form.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Post Form</title>
</head>
<body>
<h4>Editing Post</h4>
{% if post_id %}
<form action="{% url 'sample_app:edit_post' post_id=post_id %}" method="post">
{% else %}
<form action="{% url 'sample_app:create_post' %}" method="post">
{% endif %}
{% csrf_token %}
{{ form }}
<button type="submit">Send</button>
</form>
<a href="{% url 'sample_app:read_post' %}">Return</a>
</body>
</html>
This Template is called from View's create_post ()
and edit_post ()
.
Therefore, form action
is branched depending on the presence or absence of post_id
as shown below.
{% if post_id %}
<form action="{% url 'sample_app:edit_post' post_id=post_id %}" method="post">
{% else %}
<form action="{% url 'sample_app:create_post' %}" method="post">
{% endif %}
With the above, the Template has been created.
After that, if you define the routing, it should work as an application.
Finally, let's define the routing.
Routing is ** "linking URL and processing" **.
In other words, when you access http://127.0.0.1:8000/sample_app/post/create/
,
Let's define something like calling create_post ()
in View ...
This time, we will link as follows.
--Data creation: http://127.0.0.1:8000/sample_app/post/create/ --Data editing: http://127.0.0.1:8000/sample_app/post/edit/1/ --Data list: http://127.0.0.1:8000/sample_app/post/ --Data deletion: http://127.0.0.1:8000/sample_app/post/delete/1/
Let's make it.
Create a new file called my_project/sample_app/urls.py
.
my_project/sample_app/urls.py
from django.urls import path
from sample_app import views
app_name = 'sample_app'
urlpatterns = [
path('post/create/', views.create_post, name='create_post'), #Create
path('post/edit/<int:post_id>/', views.edit_post, name='edit_post'), #Fix
path('post/', views.read_post, name='read_post'), #List display
path('post/delete/<int:post_id>/', views.delete_post, name='delete_post'), #Delete
]
Next, load the created my_project/sample_app/urls.py in my_project/urls.py for the entire project.
my_project/urls.py
from django.contrib import admin
from django.urls import path, include # Add
urlpatterns = [
path('sample_app/', include('sample_app.urls')), # Add
path('admin/', admin.site.urls),
]
This will allow your project to recognize the application URL.
By the way, name ='XXX'
can be anything. (I try to align it with the function name)
If you can implement it so far, it should work as an application.
Let's run python manage.py runserver
again.
$ python manage.py runserver
Watching for file changes with StatReloader
Performing system checks...
System check identified no issues (0 silenced).
December 20, 2020 - 09:12:49
Django version 3.1.4, using settings 'my_project.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
In this state, if you access http://127.0.0.1:8000/sample_app/post/ from your browser, the data list display screen will be displayed.
It also has a create button and a modify button, so you can create data and modify or delete the created data.
Thank you for reading to the end. How was that.
Once you have created such an application feature ** Design with css, deploy to heroku, get your own domain, and you have a web service **.
The creation of Web services is summarized in the following article.
-I want to publish the product at the lowest cost -Web service made for several tens of yen
Have a good Django life next year!