Python | Django | ログの実装方法
公開日:2021/9/2
Pythonには,DjangoというWebアプリケーションフレームワークがある.フレームワークのため,Djangoを利用するとWebアプリを通常よりも短時間で開発することが可能になる.
本記事では,「ログの実装方法」を以下9つの構成にて記す.
- “log"の出力
- “logger"のインスタンス化
- “logger"の設定方法(基本)
- “logger"の設定方法(カスタマイズ)
- “log"のローテーション
- “log"のローテーションの設定方法
- 作成したサイトでのlogの設定
- ミドルウェアを追加した処理
(1) URLへのアクセスログ1
(2) URLへのアクセスログ2
(3) URLへのアクセス時間ログ - 参照
◆実施環境
Python 3.8.8
Django 3.2.3
VS Code 1.59.0
■ログの実装方法
ログの出力には以下のようなログレベルが設定されている.数字が大きいほどエラーが深刻であることを示している.なお,Pythonではログレベルを以下のように定義している.
(1) DEBUG: 低レベルのシステム情報
(2) INFO: 一般的なシステム情報
(3) WARNING: 小さい問題が発生
(4) ERROR: 大きい問題が発生
(5) CRITICAL: 重大な問題が発生
以下にフォルダの設定からログ出力を行っていく.
新たにフォルダを開く.そのため,VS Codeの"File"をクリックし,"Open Folder"からフォルダを選ぶ.
“myloggingtest"という名のフォルダを作成したので,当該フォルダを選択する.選択後,以下赤枠のようにフォルダが出来上がる.
“myloggingtest"の下の黒スペースで右クリックをすると以下画面が出力するので,"New File"をクリックする.
“1_logging_test.py"という名のファイルを以下のように作成した.
“1_logging_test.py"を以下のように編集する.
import logging
logging.basicConfig(
level=logging.WARNING, filename='example.log',
filemode='w',
format='%(asctime)s-%(process)s-%(levelname)s-%(message)s'
)
logging.debug('debug.log')
logging.info('info.log')
logging.warning('warning.log')
logging.error('error.log')
logging.critical('critical.log')
コードを記述した画面で右クリックをすると以下画面が出力するので,"Run Python File in Terminal"をクリックする.
ターミナルに以下が出力される.
PS C:\Users\shiro\Desktop\210517_python development\myloggingtest> & C:/Users/shiro/anaconda3/envs/djangoenv/python.exe "c:/Users/shiro/Desktop/210517_python development/myloggingtest/1_logging_test.py"*/
加えて,"myloggingtest"に以下のように"example.log"が出力する.
“1_logging_test.py"の4行目に"WARNING"を利用したので,"example.log"の中は,以下コードが記載される.
2021-08-26 15:56:55,020-10312-WARNING-warning.log
2021-08-26 15:56:55,020-10312-ERROR-error.log
2021-08-26 15:56:55,020-10312-CRITICAL-critical.log
“1_logging_test.py"を以下のように変更し,"Run Python File in Terminal"を実行する.
import logging
logging.basicConfig( # 変更箇所
level=logging.INFO, filename='example.log',
filemode='w',
format='%(asctime)s-%(process)s-%(levelname)s-%(message)s'
)
logging.debug('debug.log')
logging.info('info.log')
logging.warning('warning.log')
logging.error('error.log')
logging.critical('critical.log')
“example.log"の中は,以下コードが記載される.
2021-08-26 16:08:15,612-8640-INFO-info.log
2021-08-26 16:08:15,612-8640-WARNING-warning.log
2021-08-26 16:08:15,612-8640-ERROR-error.log
2021-08-26 16:08:15,612-8640-CRITICAL-critical.log
“1_logging_test.py"に以下を追記し,編集し,"Run Python File in Terminal"を実行する.
import logging
logging.basicConfig(
level=logging.INFO, filename='example.log',
filemode='w',
format='%(asctime)s-%(process)s-%(levelname)s-%(message)s'
)
logging.debug('debug.log')
logging.info('info.log')
logging.warning('warning.log')
logging.error('error.log')
logging.critical('critical.log')
name = "XYZ's PC" # 追記箇所
logging.critical(f'- {name} has error')
“example.log"の中は,以下コードが記載される.
2021-08-26 16:31:27,191-732-INFO-info.log
2021-08-26 16:31:27,191-732-WARNING-warning.log
2021-08-26 16:31:27,191-732-ERROR-error.log
2021-08-26 16:31:27,191-732-CRITICAL-critical.log
2021-08-26 16:31:27,192-732-CRITICAL-- XYZ's PC has error
“1_logging_test.py"に以下を追記し,編集し,"Run Python File in Terminal"を実行する.
import logging
logging.basicConfig(
level=logging.INFO, filename='example.log',
filemode='w',
format='%(asctime)s-%(process)s-%(levelname)s-%(message)s'
)
logging.debug('debug.log')
logging.info('info.log')
logging.warning('warning.log')
logging.error('error.log')
logging.critical('critical.log')
name = "XYZ's PC"
logging.critical(f'{name} has error')
try: # 追記箇所
result = 10/0
except Exception as e:
logging.error(e, exc_info=True)
“example.log"の中は,以下コードが出力される."1_logging_test.py"にて"exc_info=True"を記載したことによって,エラーが19行目で発生したことがわかる.
2021-08-26 17:14:02,749-13804-INFO-info.log
2021-08-26 17:14:02,749-13804-WARNING-warning.log
2021-08-26 17:14:02,749-13804-ERROR-error.log
2021-08-26 17:14:02,749-13804-CRITICAL-critical.log
2021-08-26 17:14:02,750-13804-CRITICAL-- XYZ's PC has error
2021-08-26 17:14:02,750-13804-ERROR-division by zero
Traceback (most recent call last):
File "c:/Users/shiro/Desktop/210517_python development/myloggingtest/1_logging_test.py", line 19, in
result = 10/0
ZeroDivisionError: division by zero
“2_logging_test.py"という名のファイルを以下のように作成した.
“2_logging_test.py"を以下のように編集する.
import logging
logger = logging.getLogger(__name__)
# logger level
logger.setLevel(logging.DEBUG)
# handler
st_handler = logging.StreamHandler()
fl_handler = logging.FileHandler('example2.log', encoding='utf-8')
# handler log level
st_handler.setLevel(logging.WARNING)
fl_handler.setLevel(logging.ERROR)
# Formatter
st_formatter = logging.Formatter('%(asctime)s-%(name)s-%(levelname)s-%(message)s')
fl_formatter = logging.Formatter('%(asctime)s-%(name)s-%(levelname)s-%(message)s')
# setting formatter in handler
st_handler.setFormatter(st_formatter)
fl_handler.setFormatter(fl_formatter)
# setting handler in logger
logger.addHandler(st_handler)
logger.addHandler(fl_handler)
#
logger.debug('debug log')
logger.info('info log')
logger.warning('warning log')
logger.error('error log')
logger.critical('critical log')
上記を保存し,"Run Python File in Terminal"をクリックするとターミナルには以下が出力される."2_logging_test.py"に"st_handler.setLevel(logging.WARNING)"を記述したため,"WARNING"以上の内容となっている.
PS C:\Users\shiro\Desktop\210517_python development\myloggingtest
> & C:/Users/shiro/anaconda3/envs/djangoenv/python.exe
"c:/Users/shiro/Desktop/210517_python development/myloggingtest/2_logging_test.py"
2021-08-30 14:45:34,818-__main__-WARNING-warning log # 以下出力箇所
2021-08-30 14:45:34,818-__main__-ERROR-error log
2021-08-30 14:45:34,819-__main__-CRITICAL-critical log
同時に"example2.log"ファイルが以下のように出力される.
“2_logging_test.py"に"fl_handler.setLevel(logging.ERROR)"を記述したため,"example2.log"には"ERROR"以上の内容となっている.
2021-08-30 14:49:58,857-__main__-ERROR-error log
2021-08-30 14:49:58,858-__main__-CRITICAL-critical log
“2_logging_test.py"に以下を追記し,"Run Python File in Terminal"を実行する.
import logging
logger = logging.getLogger(__name__)
# logger level
logger.setLevel(logging.DEBUG)
# handler
st_handler = logging.StreamHandler()
fl_handler = logging.FileHandler('example2.log', encoding='utf-8')
# handler log level
st_handler.setLevel(logging.WARNING)
fl_handler.setLevel(logging.ERROR)
# Formatter
st_formatter = logging.Formatter('%(asctime)s-%(name)s-%(levelname)s-%(message)s')
fl_formatter = logging.Formatter('%(asctime)s-%(name)s-%(levelname)s-%(message)s')
# setting formatter in handler
st_handler.setFormatter(st_formatter)
fl_handler.setFormatter(fl_formatter)
# setting handler in logger
logger.addHandler(st_handler)
logger.addHandler(fl_handler)
#
logger.debug('debug log')
logger.info('info log')
logger.warning('warning log')
logger.error('error log')
logger.critical('critical log')
try: # 追記箇所
result = 10/0
except Exception as e:
logger.critical(e, exc_info=True)
ターミナルには,以下が出力される.
PS C:\Users\shiro\Desktop\210517_python development\myloggingtest>
> & C:/Users/shiro/anaconda3/envs/djangoenv/python.exe
"c:/Users/shiro/Desktop/210517_python development/myloggingtest/2_logging_test.py"
2021-08-30 15:21:14,767-__main__-WARNING-warning log # 以下出力箇所
2021-08-30 15:21:14,767-__main__-ERROR-error log
2021-08-30 15:21:14,768-__main__-CRITICAL-critical log
2021-08-30 15:21:14,768-__main__-CRITICAL-division by zero
Traceback (most recent call last):
File "c:/Users/shiro/Desktop/210517_python development/myloggingtest/2_logging_test.py", line 37, in
result = 10/0
ZeroDivisionError: division by zero
加えて,"example2.log"の中には,以下コードが出力される.
2021-08-30 14:49:58,857-__main__-ERROR-error log
2021-08-30 14:49:58,858-__main__-CRITICAL-critical log
2021-08-30 15:09:23,993-__main__-ERROR-error log
2021-08-30 15:09:23,993-__main__-CRITICAL-critical log
2021-08-30 15:14:35,269-__main__-ERROR-error log
2021-08-30 15:14:35,269-__main__-CRITICAL-critical log
2021-08-30 15:21:14,767-__main__-ERROR-error log
2021-08-30 15:21:14,768-__main__-CRITICAL-critical log
2021-08-30 15:21:14,768-__main__-CRITICAL-division by zero
Traceback (most recent call last):
File "c:/Users/shiro/Desktop/210517_python development/myloggingtest/2_logging_test.py", line 37, in
result = 10/0
ZeroDivisionError: division by zero
“3_logging_test.py"という名のファイルを以下のように作成する.
“3_logging_test.py"を以下のように編集する.
import logging
import logging.config
logging.config.fileConfig(name='configtest/logger1.conf')
“3_logging_test.py"に"config/logger1.conf"を記述したので,"config"フォルダを作成し,その中に"logger1.conf"を作成する.
“logger1.conf"を以下のように編集する.なお,"[handler_filehandler]"の"args"の中の"w"は新規作成を意味する."a"に変えると追記となる.
[loggers]
keys=root
[handlers]
keys=consolehandler, filehandler
[formatters]
keys=sampleformatter
[logger_root]
level=DEBUG
handlers=consolehandler, filehandler
[handler_consolehandler]
class=StreamHandler
level=WARNING
formatter=sampleformatter
args=(sys.stdout,)
[handler_filehandler]
class=FileHandler
level=ERROR
formatter=sampleformatter
args=['logs/error.log', 'w', 'utf-8']
[formatter_sampleformatter]
format=%(asctime)s-%(name)s-%(message)s
“logger1.conf"で"logs/error.log"と記述したので,"logs"フォルダを以下のように作成する.
“3_logging_test.py"に追記し,"Run Python File in Terminal"を実行する.
import logging
import logging.config
logging.config.fileConfig(name='configtest/logger1.conf')
logger = logging.getLogger(__name__) # 以下追記箇所
logger.debug('debug log')
logger.info('info log')
logger.warning('warning log')
logger.error('error log')
logger.critical('critical log')
ターミナルには以下が出力される."configtest/logger1.conf"の"StreamHandler"が"Warning"のため,"warning"以上のログが出力されている.
PS C:\Users\shiro\Desktop\210517_python development\myloggingtest>
& C:/Users/shiro/anaconda3/envs/djangoenv/python.exe
"c:/Users/shiro/Desktop/210517_python development/myloggingtest/3_logging_test.py"
2021-08-31 14:55:55,739-__main__-warning log # 以下出力箇所
2021-08-31 14:55:55,740-__main__-error log
2021-08-31 14:55:55,741-__main__-critical log
加えて,"logs"フォルダには"error.log"が作成される.
“configtest/logger1.conf"の"FileHandler"が"Error"のため,"logs/error.log"には以下のように"error"以上が出力される.
2021-08-31 14:55:55,740-__main__-error log
2021-08-31 14:55:55,741-__main__-critical log
“configtest/logger1.conf"に追記し,以下のように編集する.以下を利用する際,#の注意書きはエラーの原因になるので,削除すること.
[loggers]
keys=root, examplelogger # 変更箇所
[handlers]
keys=consolehandler, filehandler, exampleconsolehandler # 変更箇所
[formatters]
keys=sampleformatter
[logger_root]
level=DEBUG
handlers=consolehandler, filehandler
[logger_examplelogger] # 追記箇所(14~18行目)
level=DEBUG
handlers=filehandler, exampleconsolehandler
qualname=examplelogger
propagate=0 # 1だと"logger_root"も呼び出される
[handler_consolehandler]
class=StreamHandler
level=WARNING
formatter=sampleformatter
args=(sys.stdout,)
[handler_filehandler]
class=FileHandler
level=ERROR
formatter=sampleformatter
args=['logs/error.log', 'w', 'utf-8']
[handler_exampleconsolehandler] # 追記箇所(32~36行目)
class=StreamHandler
level=INFO
formatter=sampleformatter
args=[sys.stdout,]
[formatter_sampleformatter]
format=%(asctime)s-%(name)s-%(message)s
“3_logging_test.py"に追記し,"Run Python File in Terminal"を実行する.
import logging
import logging.config
logging.config.fileConfig(fname='configtest/logger1.conf')
logger = logging.getLogger(__name__)
logger.debug('debug log')
logger.info('info log')
logger.warning('warning log')
logger.error('error log')
logger.critical('critical log')
logger = logging.getLogger('examplelogger') # 以下追記箇所
logger.debug('debug log')
logger.info('info log')
logger.warning('warning log')
logger.error('error log')
logger.critical('critical log')
ターミナルには以下が出力される.
PS C:\Users\shiro\Desktop\210517_python development\myloggingtest
> n 46: & C:/Users/shiro/anaconda3/envs/djangoenv/python.exe
"c:/Users/shriro/Desktop/210517_python development/myloggingtest/3_logging_testy& C:/U.py" top/21
2021-08-31 16:19:16,807-__main__-warning log # 以下出力箇所
2021-08-31 16:19:16,807-__main__-error log
2021-08-31 16:19:16,807-__main__-critical log
2021-08-31 16:19:16,808-examplelogger-info log
2021-08-31 16:19:16,809-examplelogger-warning log
2021-08-31 16:19:16,809-examplelogger-error log
2021-08-31 16:19:16,809-examplelogger-critical log
“4_logging_test.py"という名のファイルを以下のように作成する.
“4_logging_test.py"を以下のように編集する.その後,"Run Python File in Terminal"を実行する.
import logging
import logging.handlers
logger = logging.getLogger(__name__)
ro_handler = logging.handlers.RotatingFileHandler(
'logs/rotation.log',
maxBytes=1000,
backupCount=6,
encoding='utf-8',
)
ti_handler = logging.handlers.TimedRotatingFileHandler(
'logs/time_rotation.log',
when='S', # 15secごと
interval=15,
backupCount=6,
encoding='utf-8',
)
logger.setLevel(logging.DEBUG)
example_formatter = logging.Formatter('%(asctime)s-%(name)s-%(levelname)s-%(message)s')
ro_handler.setFormatter(example_formatter)
ti_handler.setFormatter(example_formatter)
logger.addHandler(ro_handler)
logger.addHandler(ti_handler)
import time
for _ in range(500):
logger.debug('debug log')
logger.info('info log')
logger.warning('warning log')
logger.error('error log')
logger.critical('critical log')
time.sleep(1)
“logs"フォルダには以下のようにlogファイルが出力される.
“5_logging_test.py"という名のファイルを以下のように作成する.
“5_logging_test.py"を以下のように編集する.
import logging
import logging.config
logging.config.fileConfig(fname='configtest/rot_logger1.conf')
“5_logging_test.py"で"configtest/rot_logger1.conf"を記述したので,"configtest"フォルダに"rot_logger1.conf"を以下のように作成する.
“rot_logger1.conf"を以下のように編集する.
[loggers]
keys=root
[handlers]
keys=rotatinghandler, timedrotatinghandler
[formatters]
keys=sampleformatter
[logger_root]
level=DEBUG
handlers=rotatinghandler, timedrotatinghandler
[handler_rotatinghandler]
class=handlers.RotatingFileHandler
level=INFO
formatter=sampleformatter
args=('logs/custom_rotation.log', 'a', 1000, 5, 'utf-8')
[handler_timedrotatinghandler]
class=handlers.TimedRotatingFileHandler
level=WARNING
formatter=sampleformatter
args=('logs/custom_t_rotation.log', 'S', 5, 6, 'utf-8')
[formatter_sampleformatter]
format=%(asctime)s-%(name)s-%(levelname)s-%(message)s
“5_logging_test.py"を以下のように編集する.その後,"Run Python File in Terminal"を実行する.
import logging
import logging.config
logging.config.fileConfig(fname='configtest/rot_logger1.conf')
logger = logging.getLogger(__name__)
import time
for _ in range(1000):
logger.debug('debug log')
logger.info('info log')
logger.warning('warning log')
logger.error('error log')
logger.critical('critical log')
time.sleep(1)
“logs"フォルダには以下のように"custom_rotation.log"と"custom_t_rotation.log"が出力された.
8/16~8/23に作成したプロジェクトを利用してlogの設定をする.以下は8/16と8/23に作成した記事のURLとなる.(*当該期間に以下2つの記事以外にも作成している)
8/16作成:class-based viewsの基本的な実装方法
8/23作成:class-based viewsにおけるSuccessMessageMixinの使い方
VS Codeの"File"をクリックし,"Open Folder"をクリックする.
“myclassbasedviewtest"フォルダをクリックする.クリックすると以下のように作成したプロジェクトが出現する.
“class_based_view/settings.py"の最下部に追記し,以下のように編集する.なお,"application-logger"の"level"は,"console_handler"の"level"よりも低くすることはできない.
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
LOGGING = { # 以下追記箇所
'version': 1,
'disable_existing_loggers': False,
'formatters':{
'simple':{
'format': '%(asctime)s %(levelname)s [%(pathname)s:%(lineno)s] %(message)s',
}
},
'handlers':{
'console_handler':{
'level':'DEBUG',
'class':'logging.StreamHandler',
'formatter':'simple',
}
},
'loggers':{
'application-logger':{
'handlers':['console_handler',],
'level':'DEBUG',
'propagate':False,
}
}
}
“ec_site/views.py"に追記し,以下のように編集する.
from django.shortcuts import render
from django.views.generic.base import (
View, TemplateView, RedirectView,
)
from django.views.generic.detail import DetailView
from django.views.generic.list import ListView
from django.views.generic.edit import (
CreateView, UpdateView, DeleteView,
FormView,
)
from . import forms
import random
from .models import Medicines
from datetime import datetime
from django.urls import reverse_lazy
from django.contrib.messages.views import SuccessMessageMixin
import logging # 追記箇所
application_logger = logging.getLogger('application-logger') # 追記箇所
class TopView(View):
def get(self, request, *args, **kwargs):
medicine_form = forms.MedicineForm()
return render(request, 'top.html', context={
'medicine_form': medicine_form,
})
def post(self, request, *args, **kwargs):
medicine_form = forms.MedicineForm(request.POST or None)
if medicine_form.is_valid():
medicine_form.save()
return render(request, 'top.html', context={
'medicine_form': medicine_form,
})
class HomeView(TemplateView):
template_name = 'home.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
application_logger.debug('log action in Home page!') # 追記箇所
context['name'] = kwargs.get('name')
context['alphabet'] = random.randint(0,9999)
return context
class MedicineDetailView(DetailView):
model = Medicines
template_name = 'medicine.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['time'] = datetime.now()
return context
class MedicineListView(ListView):
model = Medicines
template_name = 'medicine_list.html'
def get_queryset(self):
qs = super(MedicineListView, self).get_queryset()
if 'name' in self.kwargs:
qs = qs.filter(name__startswith=self.kwargs['name'])
qs = qs.order_by('-id')
return qs
class MedicineCreateView(CreateView):
model = Medicines
fields = ['name', 'description', 'price']
template_name = 'insert_medicine.html'
def form_valid(self, form):
form.instance.create_time = datetime.now()
form.instance.update_time = datetime.now()
return super(MedicineCreateView, self).form_valid(form)
def get_initial(self, **kwargs):
initial = super(MedicineCreateView, self).get_initial(**kwargs)
initial['price'] = '1000'
return initial
class MedicineUpdateView(SuccessMessageMixin, UpdateView):
template_name = 'update_medicine.html'
model = Medicines
form_class = forms.MedicineUpdateForm
success_message = 'Update is successful!'
def get_success_url(self):
return reverse_lazy('ec_site:update_medicine', kwargs={'pk': self.object.id})
def get_success_message(self, cleaned_data):
return cleaned_data.get('name') + ' was updated'
class MedicineDeleteView(DeleteView):
model = Medicines
template_name = 'delete_medicine.html'
success_url = reverse_lazy('ec_site:list_medicines')
class MedicineFormView(FormView):
template_name = 'form_medicine.html'
form_class = forms.MedicineForm
success_url = reverse_lazy('ec_site:list_medicines')
def get_initial(self):
initial = super(MedicineFormView, self).get_initial()
initial['price'] = '2000'
return initial
def form_valid(self, form):
if form.is_valid():
form.save()
return super(MedicineFormView, self).form_valid(form)
class MedicineRedirectView(RedirectView):
url = 'https://shelokuma.com'
def get_redirect_url(self, *args, **kwargs):
medicine = Medicines.objects.last()
if 'pk' in kwargs:
return reverse_lazy('ec_site:detail_medicine', kwargs={'pk':kwargs['pk']})
return reverse_lazy('ec_site:update_medicine', kwargs={'pk': medicine.pk})
VS Codeの"View"を開き,"Terminal"をクリックする.VS Codeの下部にターミナルが開くので,”conda activate 仮想環境名”を実行し,仮想環境に移行する(移行方法の詳細はこちら).ターミナルで"cd class_based_view"(プロジェクト名)を入力し,ディレクトリを変更する.変更後,以下のように”python manage.py runserver”を実行する.以下が出力される.
(djangoenv) C:\Users\shiro\Desktop\210517_python development\myclassbasedviewtest\class_based_view
>python manage.py runserver
Watching for file changes with StatReloader
Performing system checks...
System check identified no issues (0 silenced). # 以下出力箇所
September 01, 2021 - 16:26:29
Django version 3.2.3, using settings 'class_based_view.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.
上記の"http://127.0.0.1:8000/"をクリックすると,ブラウザが開き,以下画面が出力される.
ブラウザのURLに"http://http://127.0.0.1:8000/ec_site/home/xyz"を入力すると以下画面に遷移する.
同時にターミナルには以下が出力される.
2021-09-01 16:29:34,394 DEBUG
[C:\Users\shiro\Desktop\210517_python development\myclassbasedviewtest\class_based_view\ec_site\views.py:43]
log action in Home page!
[01/Sep/2021 16:29:34] "GET /ec_site/home/xyz HTTP/1.1" 200 82
“class_based_view/settings.py"の最下部に追記し,以下のように編集する.
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'formatters':{
'simple':{
'format': '%(asctime)s %(levelname)s [%(pathname)s:%(lineno)s] %(message)s',
}
},
'handlers':{
'console_handler':{
'level':'DEBUG',
'class':'logging.StreamHandler',
'formatter':'simple',
},
'timed_file_handler':{ # 追記箇所(143~152行目)
'level':'INFO',
'class':'logging.handlers.TimedRotatingFileHandler',
'filename':os.path.join('logs','application.log'),
'when':'S',
'backupCount':10,
'formatter':'simple',
'encoding':'utf-8',
'delay':True,
}
},
'loggers':{
'application-logger':{
'handlers':['console_handler', 'timed_file_handler'], # 変更箇所
'level':'DEBUG',
'propagate':False,
}
}
}
“ec_site/views.py"に追記し,以下のように編集する.
from django.shortcuts import render
from django.views.generic.base import (
View, TemplateView, RedirectView,
)
from django.views.generic.detail import DetailView
from django.views.generic.list import ListView
from django.views.generic.edit import (
CreateView, UpdateView, DeleteView,
FormView,
)
from . import forms
import random
from .models import Medicines
from datetime import datetime
from django.urls import reverse_lazy
from django.contrib.messages.views import SuccessMessageMixin
import logging
application_logger = logging.getLogger('application-logger')
class TopView(View):
def get(self, request, *args, **kwargs):
medicine_form = forms.MedicineForm()
return render(request, 'top.html', context={
'medicine_form': medicine_form,
})
def post(self, request, *args, **kwargs):
medicine_form = forms.MedicineForm(request.POST or None)
if medicine_form.is_valid():
medicine_form.save()
return render(request, 'top.html', context={
'medicine_form': medicine_form,
})
class HomeView(TemplateView):
template_name = 'home.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
application_logger.debug('log action in Home page!')
context['name'] = kwargs.get('name')
context['alphabet'] = random.randint(0,9999)
return context
class MedicineDetailView(DetailView):
model = Medicines
template_name = 'medicine.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['time'] = datetime.now()
return context
class MedicineListView(ListView):
model = Medicines
template_name = 'medicine_list.html'
def get_queryset(self):
qs = super(MedicineListView, self).get_queryset()
if 'name' in self.kwargs:
qs = qs.filter(name__startswith=self.kwargs['name'])
qs = qs.order_by('-id')
return qs
class MedicineCreateView(CreateView):
model = Medicines
fields = ['name', 'description', 'price']
template_name = 'insert_medicine.html'
def form_valid(self, form):
form.instance.create_time = datetime.now()
form.instance.update_time = datetime.now()
return super(MedicineCreateView, self).form_valid(form)
def get_initial(self, **kwargs):
initial = super(MedicineCreateView, self).get_initial(**kwargs)
initial['price'] = '1000'
return initial
class MedicineUpdateView(SuccessMessageMixin, UpdateView):
template_name = 'update_medicine.html'
model = Medicines
form_class = forms.MedicineUpdateForm
success_message = 'Update is successful!'
def get_success_url(self):
return reverse_lazy('ec_site:update_medicine', kwargs={'pk': self.object.id})
def get_success_message(self, cleaned_data):
application_logger.warning('update medicine!') # 追記箇所
return cleaned_data.get('name') + ' was updated'
class MedicineDeleteView(DeleteView):
model = Medicines
template_name = 'delete_medicine.html'
success_url = reverse_lazy('ec_site:list_medicines')
class MedicineFormView(FormView):
template_name = 'form_medicine.html'
form_class = forms.MedicineForm
success_url = reverse_lazy('ec_site:list_medicines')
def get_initial(self):
initial = super(MedicineFormView, self).get_initial()
initial['price'] = '2000'
return initial
def form_valid(self, form):
if form.is_valid():
form.save()
return super(MedicineFormView, self).form_valid(form)
class MedicineRedirectView(RedirectView):
url = 'https://shelokuma.com'
def get_redirect_url(self, *args, **kwargs):
medicine = Medicines.objects.last()
if 'pk' in kwargs:
return reverse_lazy('ec_site:detail_medicine', kwargs={'pk':kwargs['pk']})
return reverse_lazy('ec_site:update_medicine', kwargs={'pk': medicine.pk})
“class_based_view/settings.py"に"logs"フォルダについて記述したので,"class_based_view"プロジェクトフォルダに以下のように"logs"フォルダを作成する.
上記を保存し,ターミナルを開き,仮想環境に移行し,"cd class_based_view"ディレクトリに移行する.その後,以下のように”python manage.py runserver”を実行する.以下が出力される.
(djangoenv) C:\Users\shiro\Desktop\210517_python development\myclassbasedviewtest\class_based_view
>python manage.py runserver
Watching for file changes with StatReloader
Performing system checks...
System check identified no issues (0 silenced). # 以下出力箇所
September 02, 2021 - 15:07:41
Django version 3.2.3, using settings 'class_based_view.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.
上記の"http://127.0.0.1:8000/"をクリックすると,ブラウザが開き,以下画面が出力される.
ブラウザのURLに"http://127.0.0.1:8000/ec_site/home/jotaro"を記入すると以下画面に遷移する.
同時にターミナルには以下が出力される.なお,"logs"フォルダにlogが出力されるのは"INFO"以上なので,今回の情報は"logs"フォルダに出力されない.
2021-09-02 15:26:00,390 DEBUG
[C:\Users\shiro\Desktop\210517_python development\myclassbasedviewtest\class_based_view\ec_site\views.py:43]
log action in Home page!
[02/Sep/2021 15:26:00] "GET /ec_site/home/jotaro HTTP/1.1" 200 85
ブラウザのURLに"http://127.0.0.1:8000/ec_site/list_medicines"を記入すると以下画面に遷移する.
ブラウザのURLに"http://127.0.0.1:8000/ec_site/update_medicine/1″を記入すると以下画面に遷移する.
NameとPriceを以下のように変更し,"update"ボタンをクリックすると,上部にメッセージが出現する.
ブラウザのURLに"http://127.0.0.1:8000/ec_site/list_medicines"に戻ると以下のように内容が変更されている.
ターミナルには,以下のようにログが出力される.
2021-09-02 15:37:19,267 WARNING
[C:\Users\shiro\Desktop\210517_python development\myclassbasedviewtest\class_based_view\ec_site\views.py:94]
update medicine!
“logs"フォルダには"application.log"が作成され,以下内容が記述される.
2021-09-02 15:37:19,267 WARNING
[C:\Users\shiro\Desktop\210517_python development\myclassbasedviewtest\class_based_view\ec_site\views.py:94]
update medicine!
“ec_site/views.py"に追記し,以下のように編集する.
from django.shortcuts import render
from django.views.generic.base import (
View, TemplateView, RedirectView,
)
from django.views.generic.detail import DetailView
from django.views.generic.list import ListView
from django.views.generic.edit import (
CreateView, UpdateView, DeleteView,
FormView,
)
from . import forms
import random
from .models import Medicines
from datetime import datetime
from django.urls import reverse_lazy
from django.contrib.messages.views import SuccessMessageMixin
import logging
from django.http import Http404 # 追記箇所
application_logger = logging.getLogger('application-logger')
class TopView(View):
def get(self, request, *args, **kwargs):
medicine_form = forms.MedicineForm()
return render(request, 'top.html', context={
'medicine_form': medicine_form,
})
def post(self, request, *args, **kwargs):
medicine_form = forms.MedicineForm(request.POST or None)
if medicine_form.is_valid():
medicine_form.save()
return render(request, 'top.html', context={
'medicine_form': medicine_form,
})
class HomeView(TemplateView):
template_name = 'home.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
application_logger.debug('log action in Home page!')
if kwargs.get('name') == 'bad': # 追記箇所(45~46行目)
raise Http404("You can't use this name")
context['name'] = kwargs.get('name')
context['alphabet'] = random.randint(0,9999)
return context
class MedicineDetailView(DetailView):
model = Medicines
template_name = 'medicine.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['time'] = datetime.now()
return context
class MedicineListView(ListView):
model = Medicines
template_name = 'medicine_list.html'
def get_queryset(self):
qs = super(MedicineListView, self).get_queryset()
if 'name' in self.kwargs:
qs = qs.filter(name__startswith=self.kwargs['name'])
qs = qs.order_by('-id')
return qs
class MedicineCreateView(CreateView):
model = Medicines
fields = ['name', 'description', 'price']
template_name = 'insert_medicine.html'
def form_valid(self, form):
form.instance.create_time = datetime.now()
form.instance.update_time = datetime.now()
return super(MedicineCreateView, self).form_valid(form)
def get_initial(self, **kwargs):
initial = super(MedicineCreateView, self).get_initial(**kwargs)
initial['price'] = '1000'
return initial
class MedicineUpdateView(SuccessMessageMixin, UpdateView):
template_name = 'update_medicine.html'
model = Medicines
form_class = forms.MedicineUpdateForm
success_message = 'Update is successful!'
def get_success_url(self):
return reverse_lazy('ec_site:update_medicine', kwargs={'pk': self.object.id})
def get_success_message(self, cleaned_data):
application_logger.warning('update medicine!')
return cleaned_data.get('name') + ' was updated'
class MedicineDeleteView(DeleteView):
model = Medicines
template_name = 'delete_medicine.html'
success_url = reverse_lazy('ec_site:list_medicines')
class MedicineFormView(FormView):
template_name = 'form_medicine.html'
form_class = forms.MedicineForm
success_url = reverse_lazy('ec_site:list_medicines')
def get_initial(self):
initial = super(MedicineFormView, self).get_initial()
initial['price'] = '2000'
return initial
def form_valid(self, form):
if form.is_valid():
form.save()
return super(MedicineFormView, self).form_valid(form)
class MedicineRedirectView(RedirectView):
url = 'https://shelokuma.com'
def get_redirect_url(self, *args, **kwargs):
medicine = Medicines.objects.last()
if 'pk' in kwargs:
return reverse_lazy('ec_site:detail_medicine', kwargs={'pk':kwargs['pk']})
return reverse_lazy('ec_site:update_medicine', kwargs={'pk': medicine.pk})
“class_based_view/settings.py"の最下部に追記し,以下のように編集する.
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'formatters':{
'simple':{
'format': '%(asctime)s %(levelname)s [%(pathname)s:%(lineno)s] %(message)s',
}
},
'handlers':{
'console_handler':{
'level':'DEBUG',
'class':'logging.StreamHandler',
'formatter':'simple',
},
'timed_file_handler':{
'level':'INFO',
'class':'logging.handlers.TimedRotatingFileHandler',
'filename':os.path.join('logs','application.log'),
'when':'S',
'backupCount':10,
'formatter':'simple',
'encoding':'utf-8',
'delay':True,
}, # 追記箇所(152~161行目)
'timed_warning_handler':{
'level':'WARNING',
'class':'logging.handlers.TimedRotatingFileHandler',
'filename':os.path.join('logs','application_warning.log'),
'when':'S',
'backupCount':10,
'formatter':'simple',
'encoding':'utf-8',
'delay':True,
}
},
'loggers':{
'application-logger':{
'handlers':['console_handler', 'timed_file_handler'],
'level':'DEBUG',
'propagate':False,
}, # 追記箇所(169~173行目)
'warning-logger':{
'handlers':['timed_warning_handler'],
'level':'WARNING',
'propagate':False,
}
}
}
“ec_site/views.py"に追記し,以下のように編集する.
from django.shortcuts import render
from django.views.generic.base import (
View, TemplateView, RedirectView,
)
from django.views.generic.detail import DetailView
from django.views.generic.list import ListView
from django.views.generic.edit import (
CreateView, UpdateView, DeleteView,
FormView,
)
from . import forms
import random
from .models import Medicines
from datetime import datetime
from django.urls import reverse_lazy
from django.contrib.messages.views import SuccessMessageMixin
import logging
from django.http import Http404
application_logger = logging.getLogger('application-logger')
warning_logger = logging.getLogger('warning-logger') # 追記箇所
class TopView(View):
def get(self, request, *args, **kwargs):
medicine_form = forms.MedicineForm()
return render(request, 'top.html', context={
'medicine_form': medicine_form,
})
def post(self, request, *args, **kwargs):
medicine_form = forms.MedicineForm(request.POST or None)
if medicine_form.is_valid():
medicine_form.save()
return render(request, 'top.html', context={
'medicine_form': medicine_form,
})
class HomeView(TemplateView):
template_name = 'home.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
application_logger.debug('log action in Home page!')
if kwargs.get('name') == 'bad': # 追記箇所(46~48行目)
warning_logger.warning("You can't use 'bad'!")
raise Http404("You can't use this 'bad'!")
context['name'] = kwargs.get('name')
context['alphabet'] = random.randint(0,9999)
return context
class MedicineDetailView(DetailView):
model = Medicines
template_name = 'medicine.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['time'] = datetime.now()
return context
class MedicineListView(ListView):
model = Medicines
template_name = 'medicine_list.html'
def get_queryset(self):
qs = super(MedicineListView, self).get_queryset()
if 'name' in self.kwargs:
qs = qs.filter(name__startswith=self.kwargs['name'])
qs = qs.order_by('-id')
return qs
class MedicineCreateView(CreateView):
model = Medicines
fields = ['name', 'description', 'price']
template_name = 'insert_medicine.html'
def form_valid(self, form):
form.instance.create_time = datetime.now()
form.instance.update_time = datetime.now()
return super(MedicineCreateView, self).form_valid(form)
def get_initial(self, **kwargs):
initial = super(MedicineCreateView, self).get_initial(**kwargs)
initial['price'] = '1000'
return initial
class MedicineUpdateView(SuccessMessageMixin, UpdateView):
template_name = 'update_medicine.html'
model = Medicines
form_class = forms.MedicineUpdateForm
success_message = 'Update is successful!'
def get_success_url(self):
return reverse_lazy('ec_site:update_medicine', kwargs={'pk': self.object.id})
def get_success_message(self, cleaned_data):
application_logger.warning('update medicine!')
return cleaned_data.get('name') + ' was updated'
class MedicineDeleteView(DeleteView):
model = Medicines
template_name = 'delete_medicine.html'
success_url = reverse_lazy('ec_site:list_medicines')
class MedicineFormView(FormView):
template_name = 'form_medicine.html'
form_class = forms.MedicineForm
success_url = reverse_lazy('ec_site:list_medicines')
def get_initial(self):
initial = super(MedicineFormView, self).get_initial()
initial['price'] = '2000'
return initial
def form_valid(self, form):
if form.is_valid():
form.save()
return super(MedicineFormView, self).form_valid(form)
class MedicineRedirectView(RedirectView):
url = 'https://shelokuma.com'
def get_redirect_url(self, *args, **kwargs):
medicine = Medicines.objects.last()
if 'pk' in kwargs:
return reverse_lazy('ec_site:detail_medicine', kwargs={'pk':kwargs['pk']})
return reverse_lazy('ec_site:update_medicine', kwargs={'pk': medicine.pk})
VS Codeのターミナルを開き,仮想環境に移行する.ターミナルで"cd class_based_view"のディレクトリに移行し,以下のように”python manage.py runserver”を実行する.以下が出力される.
(djangoenv) C:\Users\shiro\Desktop\210517_python development\myclassbasedviewtest\class_based_view
>python manage.py runserver
Watching for file changes with StatReloader
Performing system checks...
System check identified no issues (0 silenced). # 以下出力箇所
September 02, 2021 - 16:43:17
Django version 3.2.3, using settings 'class_based_view.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.
上記の"http://127.0.0.1:8000/"をクリックすると,ブラウザが開く.ブラウザのURLに"http://127.0.0.1:8000/ec_site/home/bad"を入力すると以下画面に遷移する."http://127.0.0.1:8000/ec_site/home/"の後ろに"bad"を加えたためである.
“logs"フォルダには以下のように"application_warning.log"が作成される.
“logs/application_warning.log"には以下のようにlogが出力される.
2021-09-02 16:49:14,712 WARNING
[C:\Users\shiro\Desktop\210517_python development\myclassbasedviewtest\class_based_view\ec_site\views.py:47]
You can't use 'bad'!
“class_based_view"フォルダに"middleware.py"を以下のように作成する.
“class_based_view/middleware.py"を以下のように編集する.
import logging
from django.utils.deprecation import MiddlewareMixin
application_logger = logging.getLogger('application-logger')
class MiddlewareTest(MiddlewareMixin):
def process_view(self, request, view_func, view_args, view_kwargs):
application_logger.info(request.get_full_path())
“class_based_view/settings.py"の"MIDDLEWARE"に以下のように編集をする.
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'ec_site',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'class_based_view.middleware.MiddlewareTest', # 追記箇所
]
VS Codeのターミナルを開き,仮想環境に移行する.ターミナルで"cd class_based_view"のディレクトリに移行し,以下のように”python manage.py runserver”を実行する.以下が出力される.
(djangoenv) C:\Users\shiro\Desktop\210517_python development\myclassbasedviewtest\class_based_view
>python manage.py runserver
Watching for file changes with StatReloader
Performing system checks...
System check identified no issues (0 silenced). # 以下出力箇所
September 02, 2021 - 18:09:56
Django version 3.2.3, using settings 'class_based_view.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.
上記の"http://127.0.0.1:8000/"をクリックすると,ブラウザが開く.ブラウザのURLに"http://127.0.0.1:8000/ec_site/list_medicines"を入力すると以下画面に遷移する.
ターミナルには以下が出力される.
2021-09-02 18:10:37,668 INFO
[C:\Users\shiro\Desktop\210517_python development\myclassbasedviewtest\class_based_view\class_based_view\middleware.py:9]
/ec_site/list_medicines
同時に,"logs/application.log"には以下ログが出力される.
2021-09-02 18:10:37,668 INFO
[C:\Users\shiro\Desktop\210517_python development\myclassbasedviewtest\class_based_view\class_based_view\middleware.py:9]
/ec_site/list_medicines
“class_based_view/middleware.py"に追記し,以下のように編集する.
import logging
from django.utils.deprecation import MiddlewareMixin
application_logger = logging.getLogger('application-logger')
warning_logger = logging.getLogger('warning-logger') # 追記箇所
class MiddlewareTest(MiddlewareMixin):
def process_view(self, request, view_func, view_args, view_kwargs):
application_logger.info(request.get_full_path())
def process_exception(self, request, exception): # 追記箇所(12~13行目)
warning_logger.warning(exception, exc_info=True)
“ec_site/views.py"を以下のように編集する.
from django.shortcuts import render
from django.views.generic.base import (
View, TemplateView, RedirectView,
)
from django.views.generic.detail import DetailView
from django.views.generic.list import ListView
from django.views.generic.edit import (
CreateView, UpdateView, DeleteView,
FormView,
)
from . import forms
import random
from .models import Medicines
from datetime import datetime
from django.urls import reverse_lazy
from django.contrib.messages.views import SuccessMessageMixin
import logging
from django.http import Http404
application_logger = logging.getLogger('application-logger')
warning_logger = logging.getLogger('warning-logger')
class TopView(View):
def get(self, request, *args, **kwargs):
medicine_form = forms.MedicineForm()
return render(request, 'top.html', context={
'medicine_form': medicine_form,
})
def post(self, request, *args, **kwargs):
medicine_form = forms.MedicineForm(request.POST or None)
if medicine_form.is_valid():
medicine_form.save()
return render(request, 'top.html', context={
'medicine_form': medicine_form,
})
class HomeView(TemplateView):
template_name = 'home.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
application_logger.debug('log action in Home page!')
if kwargs.get('name') == 'bad': # 変更箇所(47行目を削除)
raise Http404("You can't use this 'bad'!")
context['name'] = kwargs.get('name')
context['alphabet'] = random.randint(0,9999)
return context
class MedicineDetailView(DetailView):
model = Medicines
template_name = 'medicine.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['time'] = datetime.now()
return context
class MedicineListView(ListView):
model = Medicines
template_name = 'medicine_list.html'
def get_queryset(self):
qs = super(MedicineListView, self).get_queryset()
if 'name' in self.kwargs:
qs = qs.filter(name__startswith=self.kwargs['name'])
qs = qs.order_by('-id')
return qs
class MedicineCreateView(CreateView):
model = Medicines
fields = ['name', 'description', 'price']
template_name = 'insert_medicine.html'
def form_valid(self, form):
form.instance.create_time = datetime.now()
form.instance.update_time = datetime.now()
return super(MedicineCreateView, self).form_valid(form)
def get_initial(self, **kwargs):
initial = super(MedicineCreateView, self).get_initial(**kwargs)
initial['price'] = '1000'
return initial
class MedicineUpdateView(SuccessMessageMixin, UpdateView):
template_name = 'update_medicine.html'
model = Medicines
form_class = forms.MedicineUpdateForm
success_message = 'Update is successful!'
def get_success_url(self):
return reverse_lazy('ec_site:update_medicine', kwargs={'pk': self.object.id})
def get_success_message(self, cleaned_data):
application_logger.warning('update medicine!')
return cleaned_data.get('name') + ' was updated'
class MedicineDeleteView(DeleteView):
model = Medicines
template_name = 'delete_medicine.html'
success_url = reverse_lazy('ec_site:list_medicines')
class MedicineFormView(FormView):
template_name = 'form_medicine.html'
form_class = forms.MedicineForm
success_url = reverse_lazy('ec_site:list_medicines')
def get_initial(self):
initial = super(MedicineFormView, self).get_initial()
initial['price'] = '2000'
return initial
def form_valid(self, form):
if form.is_valid():
form.save()
return super(MedicineFormView, self).form_valid(form)
class MedicineRedirectView(RedirectView):
url = 'https://shelokuma.com'
def get_redirect_url(self, *args, **kwargs):
medicine = Medicines.objects.last()
if 'pk' in kwargs:
return reverse_lazy('ec_site:detail_medicine', kwargs={'pk':kwargs['pk']})
return reverse_lazy('ec_site:update_medicine', kwargs={'pk': medicine.pk})
VS Codeのターミナルを開き,仮想環境に移行する.ターミナルで"cd class_based_view"のディレクトリに移行し,以下のように”python manage.py runserver”を実行する.以下が出力される.
(djangoenv) C:\Users\shiro\Desktop\210517_python development\myclassbasedviewtest\class_based_view
>python manage.py runserver
Watching for file changes with StatReloader
Performing system checks...
System check identified no issues (0 silenced). # 以下出力箇所
September 02, 2021 - 18:30:25
Django version 3.2.3, using settings 'class_based_view.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.
上記の"http://127.0.0.1:8000/"をクリックすると,ブラウザが開く.ブラウザのURLに"http://127.0.0.1:8000/ec_site/home/"の後ろに"bad"を付けて入力すると以下画面に遷移する.
“class_based_view/logs/application_warning.log"には以下のようなログが出力される.
2021-09-02 18:38:16,096 WARNING [C:\Users\shiro\Desktop\210517_python development\myclassbasedviewtest\class_based_view\class_based_view\middleware.py:13] You can't use this 'bad'!
Traceback (most recent call last):
File "C:\Users\shiro\anaconda3\envs\djangoenv\lib\site-packages\django\core\handlers\base.py", line 181, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Users\shiro\anaconda3\envs\djangoenv\lib\site-packages\django\views\generic\base.py", line 70, in view
return self.dispatch(request, *args, **kwargs)
File "C:\Users\shiro\anaconda3\envs\djangoenv\lib\site-packages\django\views\generic\base.py", line 98, in dispatch
return handler(request, *args, **kwargs)
File "C:\Users\shiro\anaconda3\envs\djangoenv\lib\site-packages\django\views\generic\base.py", line 159, in get
context = self.get_context_data(**kwargs)
File "C:\Users\shiro\Desktop\210517_python development\myclassbasedviewtest\class_based_view\ec_site\views.py", line 48, in get_context_data
raise Http404("You can't use this 'bad'!")
django.http.response.Http404: You can't use this 'bad'!
“class_based_view/settings.py"の"LOGGING"を以下のように編集する.
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'formatters':{
'simple':{
'format': '%(asctime)s %(levelname)s [%(pathname)s:%(lineno)s] %(message)s',
}
},
'handlers':{
'console_handler':{
'level':'DEBUG',
'class':'logging.StreamHandler',
'formatter':'simple',
},
'timed_file_handler':{
'level':'INFO',
'class':'logging.handlers.TimedRotatingFileHandler',
'filename':os.path.join('logs','application.log'),
'when':'S',
'backupCount':10,
'formatter':'simple',
'encoding':'utf-8',
'delay':True,
}, # 追記箇所(153~162行目)
'timed_info_handler':{
'level':'INFO',
'class':'logging.handlers.TimedRotatingFileHandler',
'filename':os.path.join('logs','application_info.log'),
'when':'S',
'backupCount':10,
'formatter':'simple',
'encoding':'utf-8',
'delay':True,
},
'timed_warning_handler':{
'level':'WARNING',
'class':'logging.handlers.TimedRotatingFileHandler',
'filename':os.path.join('logs','application_warning.log'),
'when':'S',
'backupCount':10,
'formatter':'simple',
'encoding':'utf-8',
'delay':True,
}
},
'loggers':{
'application-logger':{
'handlers':['console_handler', 'timed_file_handler'],
'level':'DEBUG',
'propagate':False,
},
'warning-logger':{
'handlers':['timed_warning_handler'],
'level':'WARNING',
'propagate':False,
}, # 追記箇所(186~190行目)
'info-logger':{
'handlers':['timed_info_handler'],
'level':'INFO',
'propagate':False,
}
}
}
“class_based_view/middleware.py"に追記し,以下のように編集する.
import logging
from django.utils.deprecation import MiddlewareMixin
import time # 追記箇所
application_logger = logging.getLogger('application-logger')
warning_logger = logging.getLogger('warning-logger')
info_logger = logging.getLogger('info-logger') # 追記箇所
class MiddlewareTest(MiddlewareMixin):
def process_view(self, request, view_func, view_args, view_kwargs):
application_logger.info(request.get_full_path())
def process_exception(self, request, exception):
warning_logger.warning(exception, exc_info=True)
class InfoMiddleware(MiddlewareMixin): # 以下追記箇所
def process_view(self, request, view_func, view_args, view_kwargs):
start_time = time.time()
request.start_time = start_time
def process_template_response(self, request, response):
response_time = time.time() - request.start_time
info_logger.info(f'{request.get_full_path()}: {response_time}sec!')
return response
“class_based_view/settings.py"の"MIDDLEWARE"に追記し,以下のように編集する.時間を計測するので,"MIDDLEWARE"の一番上に追記するのがベストとなる.
MIDDLEWARE = [
'class_based_view.middleware.InfoMiddleware', # 追記箇所
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'class_based_view.middleware.MiddlewareTest',
]
VS Codeのターミナルを開き,仮想環境に移行する.ターミナルで"cd class_based_view"のディレクトリに移行し,以下のように”python manage.py runserver”を実行する.以下が出力される.
(djangoenv) C:\Users\shiro\Desktop\210517_python development\myclassbasedviewtest\class_based_view
>python manage.py runserver
Watching for file changes with StatReloader
Performing system checks...
System check identified no issues (0 silenced). # 以下出力箇所
September 02, 2021 - 19:05:45
Django version 3.2.3, using settings 'class_based_view.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.
上記の"http://127.0.0.1:8000/"をクリックすると,ブラウザが開く.ブラウザのURLに"http://127.0.0.1:8000/ec_site/list_medicines"を入力すると以下画面に遷移する.
“class_based_view/logs"には"application_ingo.log"が以下のように作成される.
“class_based_view/logs/application_ingo.log"には以下が出力される."http://127.0.0.1:8000/ec_site/list_medicines"を表示させるのに,"0.004988193511962891″秒かかることがわかる.
2021-09-02 19:08:12,174 INFO
[C:\Users\shiro\Desktop\210517_python development\myclassbasedviewtest\class_based_view\class_based_view\middleware.py:25]
/ec_site/list_medicines: 0.004988193511962891sec!
https://docs.djangoproject.com/en/3.2/topics/logging/
https://docs.python.org/ja/3/howto/logging.html#logging-to-a-file
https://docs.python.org/ja/3/howto/logging.html#formatters
https://docs.djangoproject.com/ja/3.1/topics/logging/
https://docs.djangoproject.com/ja/3.1/topics/http/middleware/
以上