LoginSignup
1
2

More than 3 years have passed since last update.

おつまみrecommender進捗(メモ)

Last updated at Posted at 2020-11-06

やりたいこと

  • クイズフォーム:好きなおつまみを選択する形式にする
  • クイズで表示されるおつまみを毎回ランダムに選ぶ
  • フロントからクイズの結果を受け取る
  • クイズの結果を用いておつまみをpredictする
  • predictしたランキングをフロントに送信する
  • アンケート結果をDBに登録する

できなかったこと

  • 画像の扱い方まだわからん
  • jSONで受け取ってページ遷移⇒結果を出力
  • 画像アップロードからお酒推定⇒PREDICTに渡す

クイズフォーム(ラジオボタン作成)+クイズで表示されるおつまみを毎回ランダムに選ぶ+

image.png

forms.py

ns = random.sample(range(15,83), 9)

def decide_coice(count, CHOICE_dict):
    CHOICEs = {
        (ns[count*3], CHOICE_dict[ns[count*3]]),
        (ns[count*3+1], CHOICE_dict[ns[count*3+1]]),
        (ns[count*3+2], CHOICE_dict[ns[count*3+2]])
    }
    return CHOICEs

CHOICESAKE = {
    (1,'1'),
    (2,'2'),
    (3,'3'),
}
CHOICE_dict = {
    15:'サラダ系',
    16:'野菜スティック',
    ()
    82: 'フルーツのアイス',
}
CHOICE = {
    (15,'サラダ系'),
   
    (82, 'フルーツのアイス'),
}

class RadioForm(forms.Form):
    select = forms.ChoiceField(label='酒', widget=forms.RadioSelect, choices= CHOICESAKE, initial=2)
    select2 = forms.ChoiceField(label='属性2', widget=forms.RadioSelect, choices= decide_coice(0, CHOICE_dict), initial=15)
    select3 = forms.ChoiceField(label='属性3', widget=forms.RadioSelect, choices= decide_coice(1, CHOICE_dict), initial=15)
    select4 = forms.ChoiceField(label='属性4', widget=forms.RadioSelect, choices= decide_coice(2,CHOICE_dict), initial=15)


formsで入力を受け取る処理を書きます。
CHICEとCHICE_dictがあるのは処理の都合上です。1つでうまいこと処理する方法は必ずあります。
画像から酒分類の処理がまだできてないからCHOICESAKEで酒の値を与えてる。ここに酒の番号を与えたい。

乱数を生成して、その番号に対応するおつまみをクイズとして表示している。

フロントからクイズの結果を受け取る

frontend/views.py
def new(request):
    params = {'message': '', 'form': None}
    if request.method == 'POST':
        #form = QuizForm(request.POST)
        form = RadioForm(request.POST)
        if form.is_valid():
            """
            redirect_url = '/newview'
            form = urlencode(QuizForm(request.POST))
            url = f'{redirect_url}?{form}'
            return redirect(url)
            """

            key = (int(form.data['select']), int(form.data['select2']), int(form.data['select3']), int(form.data['select4']))
            return recommend(request, key[0], key[1], key[2], key[3])


        else:
            params['message'] = '再入力して下さい'
            params['form'] = form
    else:
        params['form'] = RadioForm()
    return render(request, 'frontend/new.html', params)

quizのページ作ってくれてたけど触るの忍びなかったからnewでクイズを作りました。
form = RadioForm(request.POST)formQueryset型でクイズの結果が入ってます。
クイズ送信時に値が正常だったらreturn recommend(request, key[0], key[1], key[2], key[3])で次の処理に移ります。

ここで問題が発生

ほんとならfrontend/recommendにページ遷移して結果を表示したかったんですけど、jsonのデータを渡す方法がわからなかったです

  • URLに引数を含めて次のページ遷移、URLから値をゲット
  • 関数に直接渡す
  • クイズ結果をDBに格納して、recommendで改めて取り出す。

の2つが実現できそうで、2つ目を選びました。その結果処理はずっと/newのURLで行われるようになってます。一応3つ目も実装はしました。
引数は全部intでこの番号っていうのは最初に出てきてCHOICEの番号と対応してます。
return recommend(request, 酒の番号, おつまみ番号1, おつまみ番号2, おつまみ番号3)

クイズの結果を用いておつまみをpredictする

処理の流れは以下


1.ユーザーが選択した酒の評価が高いデータを取り出すfindsameperson()
2.ユーザーが選択したおつまみを参考に類似度を計算get_simiralities()
3.類似度で並べ替えてランキング付けpredict()


views.py
quizAnser = [CHOICE_dict[one+3], CHOICE_dict[two], CHOICE_dict[three], CHOICE_dict[four]]

    #画像とクイズから得られたターゲットデータ
    target_sake = target_items_list[one+3]
    first_otsumami = {target_items_list[two] : two}
    second_otsumami = {target_items_list[three] : three}
    target_data = [first_otsumami, second_otsumami]
    sample_lists = list(Sample.objects.all().values())


    #選んだ酒の評価が高い人のサンプルデータを取得
    samePersonList = findsamePerson(target_sake, sample_lists)

    #類似度を計算
    similarities = get_similarities(samePersonList, target_data)

    #ランキング付ける
    ranking = predict(samePersonList, similarities, target_items_list, CHOICE_dict)

    params = {
        'title': 'title',
        'massage': similarities,
        '酒の種類':quizAnser[0],
        'おつまみ1':quizAnser[1],
        'おつまみ2':quizAnser[2],
        'おつまみ3':quizAnser[3],
        '1位':ranking[0][0],
        'quizAnser': quizAnser,
        'data': ranking,
    }
    return render(request, 'frontend/recommend.html', context=params)

def findsamePerson(target_sake, sample_lists):#(str, list[dict])
    #ターゲットの酒の評価が5のサンプルを抽出する
    #評価が高い人のデータ(辞書型)をsamePersonListに入れていく

    samePersonList = []
    for item in sample_lists:
        if item[target_sake] >= 3:
            samePersonList.append(item)
        else:
            pass
    return samePersonList

predictしたランキングをフロントに送信、表示

vies.py
    params = {
        'title': 'title',
        'massage': similarities,
        '酒の種類':quizAnser[0],#str
        'おつまみ1':quizAnser[1],#str
        'おつまみ2':quizAnser[2],
        'おつまみ3':quizAnser[3],
        '1位':ranking[0][0],#str
        'quizAnser': quizAnser,#入力結果の名称のリスト(str)[酒、おつ1、おつ2、おつ3]
        'data': ranking,#dictのリスト=[{おつまみ名1:類似度},{おつまみ名2:類似度}...]類似度でソート済み
    }
    return render(request, 'frontend/recommend.html', context=params)

paramsのkey(左)がhtmlで使えるラベルで、value(右)が実際の中身

frontend/recommend.html
                        <h2>あなたの今日のおつまみは……</h2>
                        <img src="{% static 'frontend/img/result/salad.jpg' %}">
                        <h2>{{1位}}!!!</h2>
                        <br>
                        <p>{{酒の種類}}にぴったりな、{{1位}}です。<br>
                            <br>
                            サラダの他に、以下の食材もおすすめです。<br>
                            サラダが苦手だったり、他のおつまみも併せて食べたい時は参考にしてみてください。</p>

                    </div>

                    {% for item, similarities in data %}
                    <p>
                        {{forloop.counter}}位:{{item}}【ポイント】: {{similarities}}
                    </p>

                    {% endfor %}

{{key}}でparamsの値が出力できて、{% %}でpythonの関数が使えるからループしてる。
↓出力画面
image.png

アンケートをDBに登録する

手作業で入力する地獄のような作業です。今は20個くらいしか登録できてません
また映画でも見ながらやっときます

ラーメン食べてきます。変なとこと、改善あったらslackで聞いてください!明日も時間あります!

見たサイト

DjangoとJavaScript(JS)を使用してリダイレクトさせる方法
DjangoでJSONを送受信する
DjangoでJson
【Django】ラジオボタンを設置したり、マークアップを整形したりする
パラメータを渡してリダイレクト
model内でDBを削除
(ModelChoiceField)登録画面で別モデルを参照したラジオボタンを表示(Django)
画面遷移のロジックがわからない
how to convert Querydict to python dict
formの基本
モデルからフォームを生成する

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2