Bootstrap Studioを使って作成した漢字間違い探しクイズのページをDjangoに移植してみる その17:make.html用のforms.pyの作成とviews.pyの修正

  • URLをコピーしました!
目次

Bootstrap Studio

前回、Bootstrap Studioで作成した漢字間違い探しクイズのplay.htmlでランダムに問題が出題されるように修正しました。

今回は修正が必要な最後のページ「make.html」を修正していきましょう。

こちらのページでは縦、横の漢字の数、埋め尽くす漢字、探す漢字、フォントを入力することで、自分で問題が作成できるページです。

ということでこんな感じです。

(「Twitterでシェアする」というボタンを作成したのですが、画像付きツイートを誰のアカウントからでもツイートするのは結構ハードルが高かったので、ちょっと断念。また機会があれば、頑張ってみたいと思います。)

現在のフォルダ構造はこんな感じ。

findthedifferentkanji
├── contents
│   ├── __init__.py
│   ├── admin.py
│   ├── apps.py
│   ├── forms.py
│   ├── migrations
│   │   └── __init__.py
│   ├── models.py
│   ├── static
│   │   └── contents
│   │       └── assets
│   │           ├── ...
│   │           └── img
│   │               ├── FindTheDifferentKANJI_Make.png
│   │               ├── FindTheDifferentKANJI_Play.png
│   │               ├── FindTheDifferentKanji_1920x600.jpg
│   │               ├── about.png
│   │               ├── make.png
│   │               ├── play.png
│   │               └── twitter.png
│   ├── templates
│   │   └── contents
│   │       ├── about.html
│   │       ├── index.html
│   │       ├── make.html
│   │       └── play.html
│   ├── tests.py
│   ├── urls.py
│   └── views.py
├── db.sqlite3
├── findthedifferentkanji
│   └──... 
└── manage.py

それでは始めていきましょう。

findthedifferentkanji > contents > forms.pyの作成

縦横の漢字の数、埋め尽くす漢字、探す漢字、フォントの情報を取得するため、フォームを作成していきます。

フォームを作成するには findthedifferentkanji > contents の中に「forms.py」を作成します。

内容としてはこんな感じです。

from django import forms

font_list = [('Random','ランダム'),('ShipporiMincho','しっぽり明朝'),('NotoSans_JP','Noto Sans JP'),('DelaGothicOne','Dela Gothic One'),('PottaOne','Potta One'),('HachiMaruPop','はちまるポップ'),('NewTegomin','New Tegomin')]

class MakeForm(forms.Form):
    vertical_num = forms.IntegerField(min_value=5, max_value=25)
    horizontal_num = forms.IntegerField(min_value=5, max_value=25)
    Char1 = forms.CharField(max_length=1)
    Char2 = forms.CharField(max_length=1)
    fonts_choice = forms.ChoiceField(widget=forms.RadioSelect, choices=font_list, initial='Random')

クラス「Makeform」の中を順に解説していきましょう。

最初の2行は縦(vertical)、横(horizontal)に並べる漢字の数を取得するためのフォームです。

    vertical_num = forms.IntegerField(min_value=5, max_value=25)
    horizontal_num = forms.IntegerField(min_value=5, max_value=25)

ただしあまりに数が多くなってしまうとサーバーに負荷をかけることになるので、「min_value=5, max_value=25」として最小の漢字の個数、最大の漢字の個数を制限しています。

次の2行は埋め尽くす漢字と探す漢字です。

    Char1 = forms.CharField(max_length=1)
    Char2 = forms.CharField(max_length=1)

どちらも漢字一文字なので、「max_length=1」とすることで制限しています。

(実は文字の種類は制限していないので、ひらがなやアルファベットでも可能です)

最後にフォント選択用のラジオボタンです。

fonts_choice = forms.ChoiceField(widget=forms.RadioSelect, choices=font_list, initial='Random')

こちらは最初にフォントのリストを作成し、それを指定すること(choices=font_list)で動きます。

font_list = [('Random','ランダム'),('ShipporiMincho','しっぽり明朝'),('NotoSans_JP','Noto Sans JP'),('DelaGothicOne','Dela Gothic One'),('PottaOne','Potta One'),('HachiMaruPop','はちまるポップ'),('NewTegomin','New Tegomin')]

これでforms.pyは完了です。

findthedifferentkanji > contents > views.pyの修正

次にviews.pywの修正を行っていきます。

まず今回追加する独自関数に関して解説していきます。

前回、「output_char_list」、「font_pick」、「question_fig」という三つの独自関数を追加しています。

この中で「question_fig」は縦横の漢字の数や二つの漢字、フォントから問題の画像を作成する関数なので、今回も使います。

そして今回はさらに入力された情報のログを取るため「log_write」という関数を追加します。

def log_write(make_log, timenow, vertical_num, horizontal_num, diff_char_no, char1, char2, font_name):
    with open(make_log, 'a') as f_in:
        row = f'{timenow},{vertical_num},{horizontal_num},{diff_char_no},{char1},{char2},{font_name}\n'
        f_in.write(row)

ログファイルのパス、時間、縦横の漢字の数、異なる漢字の場所、埋め尽くす漢字と探す漢字、フォントの名前を引数として、ログに書き込むということをしています。

表示する部分のプログラムはこちら。

from django.shortcuts import render
from django.http import HttpResponse
from .forms import MakeForm
import json
import random
import datetime
import matplotlib
matplotlib.use('Agg')
from matplotlib import pyplot as plt
import matplotlib.font_manager as fm

question_json = 'contents/settings/question.json'
play_fig_path = 'contents/static/contents/assets/img/FindTheDifferentKANJI_Play.png'

fonts_json = 'contents/settings/fonts.json'
make_fig_path = 'contents/static/contents/assets/img/FindTheDifferentKANJI_Make.png'
make_log = 'contents/settings/input_make.log'

def index(request):

    return render(request, 'contents/index.html')

def play(request):

    vertical, horizontal, diff_char_num, output_list, char_list = output_char_list(question_json)
    font_name, font_path = font_pick(fonts_json)

    question_fig(font_path, vertical, horizontal, output_list, play_fig_path)

    return render(request, 'contents/play.html')

def make(request):

    params = {}

    with open(fonts_json, 'r') as f_in:
        params['fonts'] = json.load(f_in)
    
    params['forms'] = MakeForm()

    if (request.method == 'POST'):

        timenow = (datetime.datetime.now() + datetime.timedelta(hours=9)).strftime("%Y/%m/%d %H:%M:%S")
        
        char1 = request.POST['Char1']
        char2 = request.POST['Char2']
        vertical_num = int(request.POST['vertical_num'])
        horizontal_num = int(request.POST['horizontal_num'])
        selected_fonts = str(request.POST['fonts_choice'])

        if selected_fonts == 'Random':
            font_name = random.choice(list(params['fonts']))
        else:
            font_name = selected_fonts
        
        font_path = params['fonts'][font_name]

        num_char = vertical_num*horizontal_num
        diff_char_no = random.randint(1, num_char)

        output_list = []
        for num in range(1, num_char+1):
            if num == diff_char_no:
                output_list.append(char2)
            else:
                output_list.append(char1)

        question_fig(font_path, vertical_num, horizontal_num, output_list, make_fig_path)

        log_write(make_log, timenow, vertical_num, horizontal_num, diff_char_no, char1, char2, font_name)

        params['forms'] = MakeForm(request.POST)

    return render(request, 'contents/make.html', params)

def about(request):

    return render(request, 'contents/about.html')

この下に独自関数が追加されることに注意してください。

まずインポートしているモジュールで追加されたのはフォームのための「from .forms import MakeForm」と時間操作のための「import datetime」です。

そして画像のファイルのパスとログファイルのパスを指定しています。

make_fig_path = 'contents/static/contents/assets/img/FindTheDifferentKANJI_Make.png'
make_log = 'contents/settings/input_make.log'

この際、前回play.htmlで使う画像のパスの変数名を「fig_path」としていましたが、分かりやすいように「play_fig_path」と変更しました。

次にmake.htmlを表示するための関数「make」を見ていきましょう。

def make(request):

    params = {}

    with open(fonts_json, 'r') as f_in:
        params['fonts'] = json.load(f_in)
    
    params['forms'] = MakeForm()

    if (request.method == 'POST'):

        timenow = (datetime.datetime.now() + datetime.timedelta(hours=9)).strftime("%Y/%m/%d %H:%M:%S")
        
        char1 = request.POST['Char1']
        char2 = request.POST['Char2']
        vertical_num = int(request.POST['vertical_num'])
        horizontal_num = int(request.POST['horizontal_num'])
        selected_fonts = str(request.POST['fonts_choice'])

        if selected_fonts == 'Random':
            font_name = random.choice(list(params['fonts']))
        else:
            font_name = selected_fonts
        
        font_path = params['fonts'][font_name]

        num_char = vertical_num*horizontal_num
        diff_char_no = random.randint(1, num_char)

        output_list = []
        for num in range(1, num_char+1):
            if num == diff_char_no:
                output_list.append(char2)
            else:
                output_list.append(char1)

        question_fig(font_path, vertical_num, horizontal_num, output_list, make_fig_path)

        log_write(make_log, timenow, vertical_num, horizontal_num, diff_char_no, char1, char2, font_name)

        params['forms'] = MakeForm(request.POST)

    return render(request, 'contents/make.html', params)

まずparamsという辞書を作成し、フォントのリストをjsonファイルから取得し、paramsに追加します。

    params = {}

    with open(fonts_json, 'r') as f_in:
        params['fonts'] = json.load(f_in)
    
    params['forms'] = MakeForm()

次に情報が入力・送信されたら、時間を取得し、それぞれのフォームに入力された値を取得します。

if (request.method == 'POST'):

        timenow = (datetime.datetime.now() + datetime.timedelta(hours=9)).strftime("%Y/%m/%d %H:%M:%S")
        
        char1 = request.POST['Char1']
        char2 = request.POST['Char2']
        vertical_num = int(request.POST['vertical_num'])
        horizontal_num = int(request.POST['horizontal_num'])
        selected_fonts = str(request.POST['fonts_choice'])

またフォントに関してはランダムという項目があるため、ランダムが選択された際はフォントリストよりランダムにフォントを選択し、それ以外の場合はそのままフォントパスを取得します。

        if selected_fonts == 'Random':
            font_name = random.choice(list(params['fonts']))
        else:
            font_name = selected_fonts
        
        font_path = params['fonts'][font_name]

取得した縦横の漢字数から並べる漢字の個数を計算し、探し出す漢字を配置する場所を決め、並べる漢字のリストを作成します。

そして必要な情報を「question_fig関数」に渡し、問題の画像を作成します。

        num_char = vertical_num*horizontal_num
        diff_char_no = random.randint(1, num_char)

        output_list = []
        for num in range(1, num_char+1):
            if num == diff_char_no:
                output_list.append(char2)
            else:
                output_list.append(char1)

        question_fig(font_path, vertical_num, horizontal_num, output_list, make_fig_path)

取得・作成した情報をログファイルに書き込みます。

        log_write(make_log, timenow, vertical_num, horizontal_num, diff_char_no, char1, char2, font_name)

ページが更新されても、入力した値が消えないように、フォームをparamsに渡し、「return render」で表示します。

        params['forms'] = MakeForm(request.POST)

    return render(request, 'contents/make.html', params)

これでviews.pyの修正は完了です。

だいぶ長くなってしまったので、今回はここまでにしましょう。

次回はmake.htmlの修正を行います。

ではでは今回はこんな感じで。

よかったらシェアしてね!
  • URLをコピーしました!

コメント

コメントする

目次
閉じる