エラーと修正歴・知識

 ここでは卒業研究等のアプリ開発で出たエラーとその解決方法をまとめる。

卒業研究で作成するアプリの概要

 これより行った実装とそのまとめを行う。

DjangoとLINEMessagingAPIを用いてオウム返しをするアプリの作成

 以下のサイトを参考に、作成した。

qiita.com

暗記カードを作成できるようにする

 「Djangoのツボとコツがゼッタイにわかる本[第2版]」を参考に作成した。

暗記カードの問題とその答えをLINEで送信する機能の追加

TypeError: Object of type Card is not JSON serializable

 「bachelor/line_botproject/utils/messagecreater.py」で、「bachelor/line_botproject/card/models.py」内の「Cardクラス」をインポートし、json化することで解消した。まずは、SUBJECTの中身を呼び出して表示させた。

# 修正前の「bachelor/line_botproject/utils/messagecreater.py」
obj = Card.objects.get(pk=2)

def create_single_text_message(message):
    if message == 'ありがとう':
        message = 'どういたしまして!'
    test_message = [
                {
                    'type': 'text',
                    'text': obj
                }
            ]
    return test_message
# 修正後の「bachelor/line_botproject/utils/messagecreater.py」
from card.models import *
import json

json.dumps(SUBJECT,indent=2,ensure_ascii=False)


def create_single_text_message(message):
    if message == 'ありがとう':
        message = 'どういたしまして!'
    test_message = [
                {
                    'type': 'text',
                    'text': SUBJECT[0][1]
                }
            ]
    return test_message

実行結果

Modelオブジェクトからjson形式に変更

 LINEのメッセージとして送信するために、ModelオブジェクトをJsonに変換した。そのために実装した「bachelor/line_botproject/utils/messagecreater.py」を以下に示す。

from card.models import *
import json
from django.forms.models import model_to_dict

def create_single_text_message(message):

    # Modelオブジェクトを取得
    post = Card.objects.get(id=1)
    # ディクショナリ型に変換
    post_dict = model_to_dict(post)
    # 辞書型からJSON型の文字列に変換
    json.dumps(post_dict)
    
    test_message = [
                {
                    'type': 'text',
                    'text': post_dict['question']+'\n'+post_dict['answer']
                }
            ]
    return test_message

実行結果

LINEメッセージに応じてカードの内容を送信する

 ここではLINEメッセージを、全部の問題、全部の回答、数字、それ以外に分類して実装を行った。
 まず、全部の問題、全部の回答を認識するために、以下のリストを作成した。

message_list = ["全部の問題","全部の回答"]

これにより、LINEメッセージがmessage_list[0]と等しければ「全部の問題」であり、LINEメッセージがmessage_list[1]と等しければ「全部の回答」であると判別できるようになった。ここでは、message_listの要素を追加すれば他のLINEメッセージにも対応できると考えた。
 次に、メッセージが数字である場合には作成したカードのidに対応して送信するような実装を行った。LINEメッセージをint型に変換する必用があることと、送られた数字がidの範囲内であることを判別する必要があることから、以下のように実装を行った。

# オブジェクトの要素数のカウント
all = Card.objects.all().count()

# LINEメッセージが数字であるかどうかの判別
def isint(s):
    try:
        int(s)
    except ValueError:
        return False
    else:
        return True

 これらを用いて条件式では「isint(message)==True&1<=int(message)&int(message)<=all」と記述し、送信された数字のLINEメッセージに応じたオブジェクトの内容をLINEで送信している。

 次に、LINEメッセージが上記のいずれでもない場合には期待されるメッセージの例を送信するようにした。具体的には、「message_list」とオブジェクトの要素数のカウントを行った「all」をstrに変換したものを「message」に結合していき送信する。そのコードを以下に示す。

all_str = str(all)
        message+=":期待されないメッセージです"+'\n'+"~以下から選択してください~"+'\n'
        message+="1~"+all_str+"の数字"+"\n"
        for i in message_list:
            message+=i+'\n'
        test_message = [
                    {
                        'type': 'text',
                        'text': message
                    }
                ]
        return test_message

 これらの実装を踏まえ、この時点での「bachelor/line_botproject/utils/message_creater.py」を以下に示す。

from card.models import *
import json

from django.forms.models import model_to_dict

all = Card.objects.all().count()
message_list = ["全部の問題","全部の回答"]
    
def isint(s):
    try:
        int(s)
    except ValueError:
        return False
    else:
        return True

def create_single_text_message(message):

    if message == message_list[0]:
        list = []
        message+=':''\n'
        
        for i in range(1,all+1):
            post = Card.objects.get(id=i)
            # ディクショナリ型に変換
            post_dict = model_to_dict(post)
            # 辞書型からJSON型の文字列に変換
            json.dumps(post_dict)
            list.append(post_dict['question'])
            message+=list[i-1]+'\n'
        
        test_message = [
                {
                    'type': 'text',
                    'text': message
                }
            ]
        return test_message

    elif message == message_list[1]:
        list = []
        message+='\n'

        for i in range(1,all+1):
            post = Card.objects.get(id=i)
            # ディクショナリ型に変換
            post_dict = model_to_dict(post)
            # 辞書型からJSON型の文字列に変換
            json.dumps(post_dict)
            list.append(post_dict['answer'])
            message+=list[i-1]+'\n'
        
        test_message = [
                {
                    'type': 'text',
                    'text': message
                }
            ]
        return test_message

    elif isint(message)==True&1<=int(message)&int(message)<=all:
        message_int = int(message)
        # Modelオブジェクトを取得
        post = Card.objects.get(id=message)
        # ディクショナリ型に変換
        post_dict = model_to_dict(post)
        # 辞書型からJSON型の文字列に変換
        json.dumps(post_dict)

        test_message = [
                    {
                        'type': 'text',
                        'text': post_dict['question']+'\n'+post_dict['answer']
                    }
                ]
        return test_message
    else:
        all_str = str(all)
        message+=":期待されないメッセージです"+'\n'+"~以下から選択してください~"+'\n'
        message+="1~"+all_str+"の数字"+"\n"
        for i in message_list:
            message+=i+'\n'
        test_message = [
                    {
                        'type': 'text',
                        'text': message
                    }
                ]
        return test_message

通知機能の追加