[PYTHON] Django hands-on

Django hands-on

environment

OS: Ubuntu 18.04 Python: 3.6.8 Django: 2.2.5 -> 2.2.8

We will add more about Windows later. I don't have a Mac, but it's probably the same as Linux (?). Add if possible.

Refer to the article Last time, and it is assumed that the directory structure is as follows. If you have not set it yet, please create the environment first.

Creating a Todo app

We will create an app from here. Type django-admin startapp mytodo on the console. You can also use python manage.py startapp mytodo.

After creation, the directory + file of the application called mytodo will be created as shown below.

.
|-- config
|   |-- __init__.py
|   |-- __pycache__
|   |-- settings.py
|   |-- urls.py
|   `-- wsgi.py
|-- db.sqlite3
|-- manage.py
|-- myenv
|   |-- bin
|   |-- include
|   `-- lib
`-- mytodo
    |-- __init__.py
    |-- admin.py
    |-- apps.py
    |-- migrations
    |-- models.py
    |-- tests.py
    `-- views.py

Set Django's timezone and language first.

settings.py


#Default'EN-en'
LANGUAGE_CODE = 'ja'
#Default'UTC'
TIME_ZONE = 'Asia/Tokyo'

Currently, the created Todo app is unknown to Django. In order for Django to recognize your application, you need to add your application to the settings in config / settings.py.

settings.py



INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'mytodo',                 #add to
]

This completes the registration of the application, and finally we will create the application.

Creating a model

For Todo, it is more practical to include the creation date and end date, but this time it will be much easier. The model defined this time is as follows.

models.py


from django.db import models


class Task(models.Model):
    doing = 0
    done = 1
    TASK_STATUS_CHOICES = [
        (doing,'in progress'),
        (done,'Done'),
    ]
    title = models.CharField(max_length=50)
    body = models.models.TextField()
    status =models.IntegerField(default=0,choices=TASK_STATUS_CHOICES)

After coding the model, run python manage.py make migrations on the console at some hierarchy in manage.py. This command creates the files needed to create the DB from the model. If it is created without error, it will be displayed as below.

(myenv)~/Projects/python/django_handson$ python manage.py makemigrations
Migrations for 'mytodo':
  mytodo/migrations/0001_initial.py
    - Create model Task

At this point, there are no changes to the DB. By passing the following python manage.py migrate command, the previous migration file will be executed for the DB.

(myenv)~/Projects/python/django_handson$ python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, mytodo, 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 mytodo.0001_initial... OK
  Applying sessions.0001_initial... OK

In addition to TODO, the character user is displayed. As an aside, the User model provided by Djnago by default is reflected in the DB.

If you can do this, the model creation is complete.

Creating a routing view template

We will implement CRUD based on the model created earlier. When developing by myself, I write in the order of view → template → routing, but I think that there are individual differences, so if you get used to it, write in your own order.

First, create a page that displays all Todo in a list. When displaying one model in one column, using Django's class-based view is a lot easier because it reduces the amount of code.

Create view

The role of the view is to get the data from the DB from the received request and return it as an embedded response in the template.

There are two ways to write a view: a function-based view and a class-based view. I'll call either, but this time I'll write in class-based view.

Class-based views include ListView, DetailView, for reference. CreateView, UpdateView, DeleteView, etc. are provided for updating. By using these, it is possible to prepare a view in an instant for simple processing.

This time I will create a list, but the necessary description is as follows.

mytodo/views.py


from django.views.generic import ListView

from mytodo.models import Task

class TaskListView(ListView):
    model = Task
    template = 'mytodo/list.html'

For model, specify the model you want to display. Import and use the model you just created. The template is a file with python control statements embedded in HTML and has the extension .html.

Creating a template

Translated into Japanese, it is called a template or type, but it is a type for embedding the value fetched from the DB etc. by the view. Embedding the value obtained from the template and DB in the view is called rendering. In the view, Django spits out an html file with embedded data based on the controls written in the template file.

{{}} Is used to display data, and {%%} is used to embed Python-like controls.

First, describe the location of the template folder in settings.py as follows.

config/settings.py


TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR,'templates')], #Change
        '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',
            ],
        },
    },
]

Create a templates folder in the same hierarchy as manage.py, and create a folder called mytodo in it.

Create a file called list.html in it. This time, we will not cover the appearance at all, so create an appropriate html file

templates/mytodo/list.html


<h1>list</h1>

<ul>
  {% for task in object_list %}
  <li><a href="#">{{ task.title }}</a> {{ task.get_status_display }}</li>
  {% endfor %}
</ul>

Routing settings

Make settings to call the appropriate view from the request url. Set in the urls.py file.

You can write everything in urls.py in the config folder, but when you create multiple apps, it will overflow with a lot of code and it will significantly impair maintainability. It also compromises the portability of the app. Therefore, it is common practice to create urls.py in the mytodo app and include it on the config side.

First, create mytodo / urls.py and edit it.

urls.py



from django.urls import path

from .views import TaskListView

app_name = 'mytodo'

urlpatterns = [
    path('',TaskListView.as_view(), name='task-list'),
]

In urls.py, associate the requested URL with the view. Add this on the config side.

config/urls.py


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


urlpatterns = [
    path('admin/', admin.site.urls),
    path('mytodo/', include('mytodo.urls',namespace='mytodo')),#add to
]

The path function can register the character string to be registered after the'/' of url in the first argument, and view and other URLConf in the second argument.

Routing is completed by creating up to this point. Let's check immediately Start the server with python manage.py runserver and check it.

You see Page not found because you haven't routed anything to the route. The registered urls are listed a little below.

rooting.png

Add mytodo to the url and access it as http://127.0.0.1:8000/mytodo. Currently, no data is registered, so only the headline is displayed. It is pure white.

no-task.png

Implementation of Create

Follow the same procedure to implement CRUD CREATE.

View

Create will be implemented using a class-based view as well. I will add it to views.py earlier.

mytodo/views.py


import django.views.generic import ListView,CreateView #Postscript

(Omission)

class TaskCreateView(CreateView):
    model = Task
    fields = '__all__'
    initial = {'status':0}
    template_name = 'mytodo/create.html'
    success_url = reverse_lazy('mytodo:task-list')

The implementation method is to register model and template in the same way as ListView. initial can set the initial state of the Choice field of the Task model. For fields, you can specify the data to be received on the server side. This time we are supposed to receive all the data, but it is also possible to receive only the title in the Task model.

template

Next, create a template.

templates/mytodo/create.html


<form action="" method="post">
  {% csrf_token %}
  {{ form.as_p }}
  <input type="submit" value="Registration">
</form>

In {{form.as_p}}, the html of the form corresponding to the model and fields of CreateView is generated. Applying css to the generated form requires some ingenuity, but this time let's enjoy the unique look of html with a taste.

Don't worry about {% csrf_token%}.

routing

Register the view in urls.py.

mytodo/urls.py


from django.urls import path

from .views import TaskListView, TaskCreateView #Postscript

app_name = 'mytodo'

urlpatterns = [
    path('',TaskListView.as_view(), name='task-list'),
    path('create',TaskCreateView.as_view(), name='task-create'),#Postscript
]

The last name in the path function can be named url. It can be used as an argument to functions such as reverse_lazy that appeared in views.py earlier.

This completes the implementation of Create. Start the server and access this URL http://127.0.0.1:8000/mytodo/create. If you see a tasty form like the one below, you're successful.

task-create.png

Let's register some as a trial.

Creating a detail screen

The rest are UPDATE and DELETE of CRUD, but create DetailView first. Currently only the list of tasks (List View), but we will create a page (Detail View) that displays more detailed information on the tasks.

Create from the view as before. The implementation is very simple as below

mytodo/views.py


from django.views.generic import ListView,CreateView,DetailView

(Omission)

class TaskDetailView(DetailView):
    model = Task
    template_name = 'mytodo/detail.html'

The template implementation is as follows: In the same way, create a file called detail.html in the templates / mytodo folder.

templates/mytodo/detail.html


<h1>Details</h1>
<div>title:{{object.title}}</div>
<div>status:{{object.get_status_display}}</div>
<div>Contents:{{object.body}}</div>
<p><a href="#">Edit</a></p>

Finally, register the URL. Path ('detail', TaskDetailView.as_view (), name ='task-detail') in the list of `ʻurl patterns ] `` Add.

This completes the implementation of DetailView.

Implement the transition from the list page to DetailView. Edit the a tag link in list.html.

templates/mytodo/detail.html


<h1>Details</h1>
<div>title:{{object.title}}</div>
<div>status:{{object.get_status_display}}</div>
<div>Contents:{{object.body}}</div>
<p><a href="{% url 'mytodo:task-update' object.pk%}">Edit</a></p> #Change

You can get the primary key of the object passed to the template with object.pk.

Implementation of update function

This will be implemented from View as well.

mytodo/views.py



from django.views.generic import ListView,CreateView,DetailView, UpdateView
from django.urls import reverse_lazy

from mytodo.models import Task

(Omission)

class TaskUpdateView(UpdateView):
    model = Task
    fields = '__all__'
    template_name = 'mytodo/update.html'
    success_url = reverse_lazy('mytodo:task-list')

It's almost the same as CreateView. If you want to limit the fields that allow updates, you can play with fields.

Since it is almost the same work, we will implement the routing and template at once.

The template is exactly the same as Create.

templates/mytodo/update.html



<form action="" method="post">
  {% csrf_token %}
  {{ form.as_p }}
  <input type="submit" value="Registration">
</form>

Add a new UpdateView to the routing. Like detail, the primary key determines which data should be updated. ..

mytodo/urls.py


urlpatterns = [
    path('',TaskListView.as_view(), name='task-list'),
    path('detail/<int:pk>/',TaskDetailView.as_view(), name='task-detail'),
    path('create/', TaskCreateView.as_view(), name='task-create'),
    path('update/<int:pk>/', TaskUpdateView.as_view(), name='task-update'),                 #add to
]

We will make some changes so that the transition to this edit screen can be performed from the details screen.

templates/mytodo/detail.html


<h1>Details</h1>
<div>title:{{object.title}}</div>
<div>status:{{object.get_status_display}}</div>
<div>Contents:{{object.body}}</div>
<p><a href="{% url 'mytodo:task-update' object.pk%}">Edit</a></p>

Addition of delete function

It's finally the end. Implement a delete view. As in the example, we will implement it from the view.

View implementation.

mytodo/views.py


from django.views.generic import ListView,CreateView,DetailView, UpdateView
from django.urls import reverse_lazy

from mytodo.models import Task

(Omission)

class TaskDeleteView(DeleteView):
    model = Task
    template_name = 'mytodo/delete.html'
    success_url = reverse_lazy('mytodo:task-list')

Template implementation. It's very simple because you can delay deleting it

templates/mytodo/delete.html


<form action="" method="post">
  {% csrf_token %}
  <p>Do you really want to delete this?</p>
  <p><input type="submit" value="Yes"></p>
  <p><a href="{% url 'mytodo:task-list' %}">Return</a></p>
</form>

Routing implementation. The final type is as follows.

mytodo/urls.py


from django.urls import path

from .views import TaskListView, TaskCreateView, TaskDetailView, TaskUpdateView, TaskDeleteView

app_name = 'mytodo'

urlpatterns = [
    path('',TaskListView.as_view(), name='task-list'),
    path('detail/<int:pk>/',TaskDetailView.as_view(), name='task-detail'),
    path('create/', TaskCreateView.as_view(), name='task-create'),
    path('update/<int:pk>/', TaskUpdateView.as_view(), name='task-update'),
    path('delete/<int:pk>/', TaskDeleteView.as_view(), name='task-delete'),            #add to
]

Finally, I added the url that transitions to this deleted view. By the way, list.html is processed by using the control statement of the template.

templates/mytodo/list.html


<h1>list</h1>

<a href="create/"><p>New addition</p></a>
<ul>
  {% for task in object_list %}
  {% if task.status != 0 %}
    <li><del><a href="detail/{{ task.id }}">{{ task.title }}</a>  </del>{{ task.get_status_display }} <a href="{% url 'mytodo:task-delete' task.pk %}">Delete</a></li>
  {% else %}
    <li><a href="detail/{{ task.id }}">{{ task.title }}</a>  {{ task.get_status_display }} <a href="{% url 'mytodo:task-delete' task.pk %}">Delete</a></li>
  {% endif %}
  
  {% empty %}
    <li>No tasks</li>
  {% endfor %}
</ul>

in conclusion

Thank you for staying with us until the end of the article about using amateur Django. If you have any mistakes, please do not hesitate to wait.

Recommended Posts

Django hands-on
Django
django update
Django note 4
django search
Django installation
Django Summary
Django test
Django # 2 (template)
Django Note 5
Touch django
django notes
Django Summary
Django basics
Django Shoho
Django defaults
Django + Docker
Django Glossary
Django search
Install Django
Django: References
Django Note 1
Django note 3
Django note 2
Django startup
Django notes
Django NullCharField
Django environment construction
Django Heroku Deploy 1
Django HTML Template # 2
Django Contact Form 2
Django begins part 1
Django model: ManyToManyField
Models in Django
Django function-based view
Python Django Tutorial (5)
Django Learning Memo
Python Django Tutorial (2)
[Django] as_view () notes
First Django Challenge
django makemigarations createsuperuser
Django related sites
Internationalization with django
Django version check
django table creation
CentOS8 --Play --Django
django tutorial memo
[Django] Redo migrate
django environment construction
Django Template notes
Python Django Tutorial (8)
Python Django Tutorial (6)
django default settings
Start Django Tutorial 1
Django HTML template
Django Template Tips
Django girls-3 workflow
Django Project Baseline
Django Heroku Deploy 2
CRUD with Django
Django class-based view