Django找不同游戏:POST请求无法正确获取异类图片ID问题
找不同游戏的ID匹配问题
我正在开发一款找不同游戏,向用户展示4张图片,其中1张为异类图片,用户选中异类图片时得分+1。当前遇到的问题是:向模板传递包含1张异类图片的4张图片后,模板中3张同类图片ID正确,但异类图片ID随机变化(期望保持其真实ID)。例如picture_ids为[1,3,4,6](6为异类图片ID),用户选中异类图片时,selected_picture_id应等于6,但实际获取到随机ID,甚至在提交用户选择前就出现随机ID的情况。
现有代码
view.py
def odd_one_out_game(request): # Get a random country country = random.choice(Country.objects.all()) print("Selected country:", country) # Get three random pictures from the selected country pictures = list(Picture.objects.filter(country=country).order_by('?')[:3]) print("Pictures from selected country:", pictures) # Get one random picture from a different country other_country = random.choice(Country.objects.exclude(pk=country.pk)) other_picture = random.choice(Picture.objects.filter(country=other_country)) other_picture_id = other_picture.id print(other_picture_id) print("Random picture from other country:", other_picture) # Add the other picture to the list of pictures pictures.append(other_picture) print("All pictures:", pictures) # Shuffle the pictures to mix up the order random.shuffle(pictures) print("Shuffled pictures:", pictures) #get the ids of the pictures picture_ids = [picture.id for picture in pictures] print("Picture IDs:", picture_ids) odd_score = request.session.get('odd_score', 0) total_guesses = request.session.get('total_guesses', 0) message = "" # Initialize message variable print("Initial score:", odd_score, "Initial total guesses:", total_guesses) if request.method == 'POST': selected_picture_id = request.POST.get('odd_one_out') selected_picture = Picture.objects.get(id=selected_picture_id) total_guesses += 1 print("Selected picture ID:", selected_picture_id) print("Selected picture:", selected_picture) print(selected_picture.country, other_country) if selected_picture.country != other_country: # Increase score by 1 if the selected picture is the odd one out odd_score += 1 message = "Congratulations! You guessed the right answer." print("Score increased:", odd_score) else: message = "Sorry! You guessed the wrong answer." print("Score unchanged:", odd_score) # Update session with the new score request.session['odd_score'] = odd_score request.session['total_guesses'] = total_guesses print("Updated score:", odd_score, "Updated total guesses:", total_guesses) context = { 'country': country, 'pictures': pictures, 'score': odd_score, 'total_guesses': total_guesses, 'message': message, } return render(request, 'odd_one_out_game.html', context)
odd_one_out_game.html
<form method="post"> {% csrf_token %} {% for picture in pictures %} <input type="radio" name="odd_one_out" id="{{ picture.id }}" value="{{ picture.id }}"> <label for="{{ picture.id }}"><img src="{{ picture.image.url }}" alt="{{ country.name }}"></label> {% endfor %} <button type="submit">Submit</button> </form>
问题根源
每次请求(不管是首次加载页面的GET请求,还是提交答案的POST请求)都会重新执行随机选图、生成异类图片的逻辑,导致POST请求时的other_country和other_picture是全新生成的,和用户看到的那组图片完全无关;同时页面加载时的异类ID也会因为重复执行逻辑出现不一致。
修复方案
将题目生成逻辑限制在首次GET请求时执行,把关键数据存入session,POST请求时从session读取数据进行判断,避免重复生成。
修改后的view.py代码
def odd_one_out_game(request): odd_score = request.session.get('odd_score', 0) total_guesses = request.session.get('total_guesses', 0) message = "" # 仅在首次加载或session无当前题目数据时生成新题目 if request.method == 'GET' or 'current_pictures' not in request.session: # 随机选目标国家 country = random.choice(Country.objects.all()) # 获取3张目标国家的图片 pictures = list(Picture.objects.filter(country=country).order_by('?')[:3]) # 获取异类图片(来自其他国家) other_country = random.choice(Country.objects.exclude(pk=country.pk)) other_picture = random.choice(Picture.objects.filter(country=other_country)) pictures.append(other_picture) random.shuffle(pictures) # 将题目关键数据存入session request.session['current_pictures'] = [pic.id for pic in pictures] request.session['correct_country_id'] = other_country.pk request.session['current_country_id'] = country.pk # 从session读取当前题目数据 picture_ids = request.session['current_pictures'] correct_country_id = request.session['correct_country_id'] current_country_id = request.session['current_country_id'] # 按session中存储的ID顺序获取图片对象(MySQL语法,其他数据库需调整) pictures = Picture.objects.filter(id__in=picture_ids).extra( select={'order': 'FIELD(id, {})'.format(','.join(map(str, picture_ids)))}, order_by=['order'] ) current_country = Country.objects.get(pk=current_country_id) if request.method == 'POST': selected_picture_id = request.POST.get('odd_one_out') selected_picture = Picture.objects.get(id=selected_picture_id) total_guesses += 1 # 判断选中的是否为异类图片 if selected_picture.country.pk == correct_country_id: odd_score += 1 message = "恭喜你!答对了!" else: message = "抱歉,答错了。" # 更新分数统计 request.session['odd_score'] = odd_score request.session['total_guesses'] = total_guesses # 清除当前题目数据,下次请求生成新题目 del request.session['current_pictures'] del request.session['correct_country_id'] del request.session['current_country_id'] context = { 'country': current_country, 'pictures': pictures, 'score': odd_score, 'total_guesses': total_guesses, 'message': message, } return render(request, 'odd_one_out_game.html', context)
关键修改说明
- 题目生成逻辑仅在首次GET请求或session无数据时执行,确保每组题目只生成一次
- 将图片ID列表、异类图片所属国家ID存入session,POST请求时直接读取,避免重新生成数据
- POST提交后清除session中的当前题目数据,保证下次请求加载新题目
- 使用
FIELD(id, ...)语法保持图片顺序与session中存储的一致(若使用PostgreSQL,需替换为POSITION(id::text IN '{}').format(','.join(map(str, picture_ids))))
模板代码无需修改,保持原代码即可。
内容的提问来源于stack exchange,提问作者Rm quiz
相关产品推荐
相关产品推荐

