[PYTHON] Snack recommender progress (memo)

Thing you want to do

What I couldn't do

Quiz form (create radio button) + Randomly select the snacks displayed in the quiz each time +

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:'Salad type',
    16:'Vegetable stick',
    (Abbreviation)
    82: 'Fruit ice cream',
}
CHOICE = {
    (15,'Salad type'),
(Omitted)
    (82, 'Fruit ice cream'),
}

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


Write a process to receive input in forms. CHICE and CHICE_dict are available for processing convenience. There is always a way to handle it well with one. Since the liquor classification process has not been completed from the image yet, the liquor value is given by CHOICE SAKE. I want to give the number of sake here.

A random number is generated and the snacks corresponding to that number are displayed as a quiz.

Receive quiz results from the front desk

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'] = 'Please re-enter'
            params['form'] = form
    else:
        params['form'] = RadioForm()
    return render(request, 'frontend/new.html', params)

He made a quiz page, but I couldn't stand to touch it, so I made a quiz with new. form = RadioForm (request.POST) and form contains the result of the quiz with Queryset type. If the value is normal when sending the quiz, press return recommend (request, key [0], key [1], key [2], key [3]) to move to the next process.

I have a problem here

I really wanted to page transition to ** frontend / recommend ** and display the result, but I didn't know how to pass json data.

It seems that the two can be realized, so I chose the second one. As a result, the processing is always done at the URL of _ / new_. I also implemented the third one. The arguments are all ints, and this number comes out first and corresponds to the CHOICE number. return recommend (request, liquor number, snack number 1, snack number 2, snack number 3)

Predict the snacks using the results of the quiz

The processing flow is as follows


    1. Retrieving highly rated data for user-selected liquor findsameperson ()
  1. Calculate similarity with reference to the snacks selected by the user get_simiralities ()
    1. Sort by similarity and rank predict ()

views.py


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

    #Target data obtained from images and quizzes
    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())


    #Get sample data of people with high evaluation of selected sake
    samePersonList = findsamePerson(target_sake, sample_lists)

    #Calculate similarity
    similarities = get_similarities(samePersonList, target_data)

    #Ranking
    ranking = predict(samePersonList, similarities, target_items_list, CHOICE_dict)

    params = {
        'title': 'title',
        'massage': similarities,
        'Type of liquor':quizAnser[0],
        'Snack 1':quizAnser[1],
        'Snack 2':quizAnser[2],
        'Snack 3':quizAnser[3],
        'First place':ranking[0][0],
        'quizAnser': quizAnser,
        'data': ranking,
    }
    return render(request, 'frontend/recommend.html', context=params)

def findsamePerson(target_sake, sample_lists):#(str, list[dict])
    #Extract samples with a target liquor rating of 5
    #Put the data (dictionary type) of people with high evaluation in the samePersonList

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

Send and display the predicted ranking to the front desk

vies.py


    params = {
        'title': 'title',
        'massage': similarities,
        'Type of liquor':quizAnser[0],#str
        'Snack 1':quizAnser[1],#str
        'Snack 2':quizAnser[2],
        'Snack 3':quizAnser[3],
        'First place':ranking[0][0],#str
        'quizAnser': quizAnser,#List of input result names(str)[Sake, Otsu 1, Otsu 2, Otsu 3]
        'data': ranking,#dict list=[{Snack name 1:Degree of similarity},{Snack name 2:Degree of similarity}...]Degree of similarityでソート済み
    }
    return render(request, 'frontend/recommend.html', context=params)

The key (left) of params is the label that can be used in html, and the value (right) is the actual contents.

frontend/recommend.html


                        <h2>Your snacks today are ...</h2>
                        <img src="{% static 'frontend/img/result/salad.jpg' %}">
                        <h2>{{First place}}!!!</h2>
                        <br>
                        <p>{{Type of liquor}}Perfect for{{First place}}is.<br>
                            <br>
In addition to salads, the following ingredients are also recommended.<br>
If you are not good at salads or want to eat other snacks, please refer to it.</p>

                    </div>

                    {% for item, similarities in data %}
                    <p>
                        {{forloop.counter}}Rank:{{item}}【point】: {{similarities}}
                    </p>

                    {% endfor %}

You can output the value of params with {{key}}, and you can use python functions with {%%}, so you are looping. ↓ Output screen image.png

Register the questionnaire in the DB

It's a hellish task to enter manually. Currently only about 20 can be registered I will do it while watching a movie

I will eat ramen. If there are any strange things or improvements, please ask on slack! I have time tomorrow!

The site I saw

How to redirect using Django and JavaScript (JS) Send and receive JSON with Django Json on Django [Django] Install radio buttons and format markup Redirect by passing parameters (https://djangobrothers.com/blogs/django_redirect_with_parameters/) Delete DB in model (ModelChoiceField) Display a radio button that refers to another model on the registration screen (Django) I don't understand the logic of screen transition how to convert Querydict to python dict form basics Generate a form from a model

Recommended Posts

Snack recommender progress (memo)