
本文详解 Django 中动态 URL 路径参数(如 search//)如何正确传递至视图函数,重点解决 search() got an unexpected keyword argument 'query' 错误,并提供可立即运行的修复方案与最佳实践。
本文详解 django 中动态 url 路径参数(如 `search/
在 Django 中,当 URL 配置使用路径转换器(path converter)(例如 path('search/<query>/', views.search, name='search')</query>)时,Django 会将匹配到的 URL 片段(如 /search/梵高/ 中的 "梵高")作为位置参数(positional argument),直接传入对应视图函数。这意味着:
✅ 正确的视图函数签名必须显式接收该参数:
def search(request, query):
# query 是从 URL 中提取的字符串,例如 "梵高"
...
❌ 若函数仅定义为 def search(request):,而 URL 配置却要求传入 query,Django 就会抛出你遇到的错误:
TypeError: search() got an unexpected keyword argument 'query'
——注意:尽管错误提示写的是 keyword argument,但实际是 Django 内部按位置传递,而函数签名不匹配导致的参数解析失败。
提供使用 django-unfold (v0.56+) 构建高级 Django 管理界面的专业指导。当用户提及 django-unfold、unfold admin 等内容时使用此技能。
✅ 正确配置示例
1. urls.py(推荐使用 path,清晰且类型安全):
from django.urls import path
from . import views
urlpatterns = [
path('', views.openapi_view, name='index'),
path('search/<query>/', views.search, name='search'), # ← 动态参数 query
]</query>
2. views.py(关键:函数签名必须含 query 参数):
import requests
from django.shortcuts import render
def search(request, query): # ← 必须添加 query 参数
base_url = "http://apis.data.go.kr/5710000/benlService/nltyArtList"
image_api_url = "http://apis.data.go.kr/5710000/benlService/artImgList"
params = {
"serviceKey": "gKat/nvnmi8i9zoiX+JsGzCTsAV75gkvU71APhj8FbnH3yX4kiZMuseZunM0ZpcvKZaMD0XsmeBHW8dVj8HQxg==",
"pageNo": "1",
"numOfRows": "5",
"returnType": "json",
"artNm": query, # ← 直接使用 URL 提取的 query,无需 request.GET.get()
}
try:
response = requests.get(base_url, params=params, timeout=10)
response.raise_for_status()
data = response.json()
art_list = data['response']['body']['items']['item']
# 批量获取图片(建议异步或缓存优化,此处为简化版)
for art in art_list:
img_params = {
"serviceKey": "gKat/nvnmi8i9zoiX+JsGzCTsAV75gkvU71APhj8FbnH3yX4kiZMuseZunM0ZpcvKZaMD0XsmeBHW8dVj8HQxg==",
"pageNo": "1",
"numOfRows": "1",
"returnType": "json",
"artNm": art["artNm"],
}
img_resp = requests.get(image_api_url, params=img_params, timeout=5)
if img_resp.status_code == 200:
img_data = img_resp.json()
items = img_data.get('response', {}).get('body', {}).get('items', {})
art["image_url"] = items.get('item', {}).get('imgUrl')
else:
art["image_url"] = None
except Exception as e:
print(f"API 호출 오류: {e}")
art_list = []
return render(request, 'index.html', {
'art_list': art_list,
'search_query': query # ← 传递给模板用于显示当前搜索词
})
⚠️ 注意事项与进阶建议
-
不要混用
request.GET.get()和路径参数:若已用<query></query>,就无需再request.GET.get('q');反之,若想保留?q=xxx查询参数风格,URL 应改为path('search/', views.search, name='search'),函数保持def search(request):,并读取request.GET.get('q', '')。 -
安全性提醒:
query来自用户输入,直接拼入 API 请求虽无 SQL 注入风险,但仍需对敏感字段做校验(如长度限制、正则过滤特殊字符),避免服务端请求被滥用。 -
用户体验优化:前端表单应提交至
/search/{{ query }}/(通过 JS 拼接)或使用重定向(HttpResponseRedirect(reverse('search', args=[query]))),确保 URL 可收藏、可分享。 -
SEO 友好性:路径参数方式(
/search/蒙娜丽莎/)比查询参数(/search/?q=蒙娜丽莎)更利于搜索引擎识别内容主题。
掌握这一机制,你就能精准控制 URL 结构与后端逻辑的映射关系,构建出语义清晰、健壮可维护的 Django 搜索功能。










