Django搜索功能报错:'NoneType' object has no attribute 'strip'
CS50W Wiki搜索功能错误修复
问题描述
开发Django搜索功能时遇到AttributeError: 'NoneType' object has no attribute 'strip',需求为:查询内容与条目名称完全匹配时跳转至条目页,不匹配时展示所有包含该查询作为子串的条目(如查询ytho显示Python)。
错误回溯
Traceback (most recent call last): File "C:\Users\anshi\.virtualenvs\storefront-bp3LZ8Cr\lib\site-packages\django\core\handlers\exception.py", line 55, in inner response = get_response(request) File "C:\Users\anshi\.virtualenvs\storefront-bp3LZ8Cr\lib\site-packages\django\core\handlers\base.py", line 197, in _get_response response = wrapped_callback(request, *callback_args, **callback_kwargs) File "D:\Python\Py Projects\CS50 attempt 00\wiki\encyclopedia\views.py", line 70, in search content = converter(search_title) File "D:\Python\Py Projects\CS50 attempt 00\wiki\encyclopedia\views.py", line 19, in converter html = Markdowner.convert(content) File "C:\Users\anshi\.virtualenvs\storefront-bp3LZ8Cr\lib\site-packages\markdown\core.py", line 248, in convert if not source.strip(): AttributeError: 'NoneType' object has no attribute 'strip' [21/Dec/2022 02:09:18] "POST /search/ HTTP/1.1" 500 72472
原代码问题分析
View层代码
def search(request): if request.method == 'POST': search_title = request.POST['q'] content = converter(search_title) if search_title is not None: return render(request, "encyclopedia/entry.html", { "entry": content, "entryTitle": search_title }) else: entries = util.list_entries() search_pages = [] for entry in entries: if search_title in entries: search_pages.append(entry) return render(request, "encyclopedia/search.html",{ "entries": search_pages })
- 逻辑判断失效:
if search_title is not None永远为真(POST参数不会为None,最多是空字符串),导致永远无法进入搜索结果分支。 - 转换器调用时机错误:直接调用
converter(search_title),当条目不存在时,转换器内部获取的内容为None,传给Markdown工具时触发strip()调用错误。 - 子串匹配逻辑错误:
if search_title in entries是检查查询内容是否在条目列表中,而非检查查询内容是否是条目名称的子串。
HTML表单代码
<form action="{% url 'search' %}" method="POST"> {% csrf_token %} <input class="search" type="text" name="q" placeholder="Search Encyclopedia"> </form>
表单本身无问题,需配合修正后的后端逻辑使用。
修复方案
修正View层代码
def search(request): if request.method == 'POST': search_title = request.POST['q'].strip() # 先调用CS50W提供的工具函数检查条目是否存在 entry_content = util.get_entry(search_title) if entry_content: # 条目存在时再转换Markdown并渲染详情页 content = converter(search_title) return render(request, "encyclopedia/entry.html", { "entry": content, "entryTitle": search_title }) else: # 条目不存在时,搜索包含子串的条目(不区分大小写) entries = util.list_entries() search_pages = [] query_lower = search_title.lower() for entry in entries: if query_lower in entry.lower(): search_pages.append(entry) return render(request, "encyclopedia/search.html", { "entries": search_pages })
修正converter函数(处理空内容情况)
确保转换器在内容不存在时返回合法值,避免Markdown转换报错:
def converter(title): content = util.get_entry(title) if not content: return "" # 或返回自定义提示内容 html = Markdowner.convert(content) return html
关键修复点
- 先判断条目存在性:调用
util.get_entry获取原始内容,确认存在后再进行Markdown转换。 - 修正子串匹配逻辑:将查询和条目名称统一转为小写,实现不区分大小写的子串匹配。
- 前置空值处理:在转换器中提前判断内容是否为空,避免传递
None给Markdown工具。
内容的提问来源于stack exchange,提问作者anshith S.Kumar
相关产品推荐
相关产品推荐

