You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django Chatterbot集成Rest API问题:请求URL时过滤菜谱被覆盖

问题分析与修复方案

核心问题

  1. 视图无状态导致数据丢失
    Django视图函数是无状态的,每次用户请求都会重新执行视图内的所有代码。你定义的state和filtered_recipes是局部变量,每次请求都会被重置为初始值(state='searching'、filtered_recipes=[])。当用户第一次发送食材获取到菜谱后,视图返回asking_for_url状态,但第二次用户回复"yes/no"时,视图又重新初始化了状态和过滤结果,导致之前的菜谱数据完全丢失。

  2. 重复调用get_response覆盖过滤结果
    在视图末尾,你第一次调用get_response后,如果状态变为asking_for_url,又用**同一个用户输入(食材内容)**再次调用get_response。此时第二次调用会进入asking_for_url分支的else逻辑,重新提取食材并过滤菜谱,直接覆盖了之前正确的filtered_recipes,导致后续无法拿到目标菜谱。


修复方案

方案1:使用Django会话(Session)保存状态与过滤结果(彻底解决)

Django的Session可以在用户的多次请求之间保存数据,是处理这类交互场景的标准方式:

from django.http import JsonResponse
from django.forms.models import model_to_dict  # 如果菜谱是ORM模型,用这个转字典

def recipe_chatbot_view(request):
    if request.method == 'POST':
        # 从会话读取状态和过滤结果,默认值为初始状态
        state = request.session.get('state', 'searching')
        # 如果菜谱是ORM对象,保存序列化后的字典;如果是普通字典直接读取
        filtered_recipes = request.session.get('filtered_recipes', [])
        message = request.POST.get('message', '').strip()

        def get_response(message, state, filtered_recipes):
            if state == 'searching':
                ingredients = extract_ingredients(message)
                filtered_recipes = filter_recipes_by_ingredients(ingredients)
                # 把ORM对象转成可序列化的字典(如果用的是普通字典可省略这步)
                filtered_recipes = [model_to_dict(recipe) for recipe in filtered_recipes]

                if filtered_recipes:
                    recipe = filtered_recipes[0]
                    state = 'asking_for_url'
                    return (
                        JsonResponse({
                            'message': f"{recipe['description']} 需要我提供这道菜的做法链接吗?"
                        }),
                        state,
                        filtered_recipes
                    )
                else:
                    state = 'no_recipes_found'
                    return (
                        JsonResponse({
                            'message': "抱歉,目前没有使用这些食材的菜谱。"
                        }),
                        state,
                        filtered_recipes
                    )

            elif state == 'asking_for_url':
                if 'yes' in message.lower():
                    if filtered_recipes:
                        recipe = filtered_recipes[0]
                        state = 'recipe_url_provided'
                        return (
                            JsonResponse({
                                'message': f"这是菜谱链接:{recipe['url']} \n 祝你烹饪愉快!"
                            }),
                            state,
                            filtered_recipes
                        )
                    else:
                        # 处理会话数据丢失的异常情况
                        state = 'searching'
                        return (
                            JsonResponse({
                                'message': "抱歉,我丢失了之前的菜谱信息,请重新输入食材。"
                            }),
                            state,
                            []
                        )
                elif 'no' in message.lower():
                    state = 'searching'
                    return (
                        JsonResponse({
                            'message': "好的,有其他需求随时告诉我。"
                        }),
                        state,
                        []
                    )
                else:
                    # 用户输入不是yes/no,重新处理食材
                    ingredients = extract_ingredients(message)
                    filtered_recipes = filter_recipes_by_ingredients(ingredients)
                    filtered_recipes = [model_to_dict(recipe) for recipe in filtered_recipes]
                    if filtered_recipes:
                        recipe = filtered_recipes[0]
                        state = 'asking_for_url'
                        return (
                            JsonResponse({
                                'message': f"{recipe['description']} 需要我提供这道菜的做法链接吗?"
                            }),
                            state,
                            filtered_recipes
                        )
                    else:
                        state = 'no_recipes_found'
                        return (
                            JsonResponse({
                                'message': "抱歉,目前没有使用这些食材的菜谱。"
                            }),
                            state,
                            filtered_recipes
                        )

            elif state == 'recipe_url_provided':
                state = 'searching'
                return (
                    JsonResponse({
                        'message': "好的,有其他需求随时告诉我,祝你烹饪开心!"
                    }),
                    state,
                    []
                )

        # 仅调用一次get_response,避免重复处理
        response, state, filtered_recipes = get_response(message, state, filtered_recipes)

        # 将更新后的状态和过滤结果保存到会话
        request.session['state'] = state
        request.session['filtered_recipes'] = filtered_recipes

        return response

方案2:临时移除重复调用代码(仅解决单次请求内的覆盖问题)

如果暂时不处理跨请求的状态保存,先删除视图末尾的重复调用代码,避免单次请求内覆盖过滤结果:

# 删掉以下两行代码
# if state == 'asking_for_url':
#     response, state, filtered_recipes = get_response(message, state, filtered_recipes)

注意:这个方案只能解决单次请求内的过滤结果覆盖问题,无法解决跨请求的状态丢失,用户第二次回复时依然会丢失之前的菜谱数据。


额外注意事项

  • 如果你的菜谱是Django ORM模型对象,不能直接保存到Session,需要用model_to_dict或自定义序列化方式转成可序列化的字典。
  • 确保项目已启用Django Session中间件(默认是启用的),并正确配置了SESSION_ENGINE。

内容的提问来源于stack exchange,提问作者Nifise Oguntoye

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 23:27:17