为什么URL路径顺序导致此Django错误?

时间:2020-07-07 18:42:18

标签: python django django-views url-routing

我正在Django中设置我的视图,以便我的首页(索引)搜索表单中的“ POST”将重定向(1)到用户想要的页面,或(2)重定向到结果列表,如果那样的话找不到页面。该选择取决于在索引视图中调用的实用程序功能。

路径1正常运行。使用路径2,我得到了Not Found: (option 2 path - what I want),之后是Value Error - The (option 1 view path - not what I want) didn't return an HttpResponseObject。看来,仅通过更改urls.py中URL模式的顺序,我才修复了该错误。我的问题是,如果我不在URL中使用正则表达式,为什么会发生这种情况?如果我的项目首先尝试重定向到正确的视图(选项2),为什么URL模式的顺序很重要?我什至从选项2路径URL中获取ValueError。

观看次数:

def index(request):
    if request.method == "POST":
        form = SearchForm(request.POST)
        if form.is_valid():
            query = form.cleaned_data['Search']
            request.session['query'] = query
            if util.get_entry(query):
                return HttpResponseRedirect(reverse("article", kwargs={'article': query}))
            else: 
                return HttpResponseRedirect(reverse("search_list"))
        else:
            return render(request, 'encyclopedia/index.html', {'form': form})    
    
    else:
        form = SearchForm()
        return render(request, "encyclopedia/index.html", {
            "entries": util.list_entries(),
            "form": SearchForm(),
        })

#I don't understand why article() is involved at all in this bug, if the condition in index() routes to searchlist()
def article(request, article):
    context = {
        "article": util.get_entry(article),
        "query": request.session['query']
    }
    if util.get_entry(article) is not None:
        return render(request, "encyclopedia/article_template.html", context)
    else:
        return HttpResponseNotFound("<h1> Nope Nope Nope </h1>")

def searchlist(request):

    # Note: right now, the search bar is giving an HttpResponseNotFound. Find out why.
    # Checks pt1: We know that request.session['query'] works 
    # because we passed it in the article view successfully

    # Checks pt2: searchlist isn't getting the context properly, because it wouldn't print
    # out query when I passed that as context.

    
    query = request.session['query']
    results_list = []
    #Write a function to check if query is a substring of a list item:  
    for entry in util.list_entries():
        if re.search(query, entry):
            results_list.append(entry)
    
    context = {
        "results": results_list, 
        "query": query,
    }
    return render(request, "encyclopedia/search_list.html", context)

应用网址

urlpatterns = [
    path("", views.index, name="index"),
    path("wiki/searchlist", views.searchlist, name='search_list'),
    path("wiki/<str:article>", views.article, name='article'),   
# Here I have switched the order of path "wiki/searchlist" and path "wiki/<str:article>" to fix this bug.
# The "article" view used to be above the "search_list" view   
]

项目网址:

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include("encyclopedia.urls"))
]

ValueError的跟踪:

Traceback (most recent call last):
  File "C:\Users\kylea\Envs\first_app\lib\site-packages\django\core\handlers\exception.py", line 34, in inner
    response = get_response(request)
  File "C:\Users\kylea\Envs\first_app\lib\site-packages\django\core\handlers\base.py", line 124, in _get_response
    raise ValueError(

Exception Type: ValueError at /wiki/searchlist
Exception Value: The view encyclopedia.views.article didn't return an HttpResponse object. It returned None instead.

3 个答案:

答案 0 :(得分:1)

据我所知

这是因为python如何工作 Python是一种解释型语言,因此可以逐行运行,因此匹配的第一个正则表达式将起作用。

最好首先使用最严格的正则表达式,最后使用最宽松的regex。

更新:格式化和正则表达式->字符串匹配

答案 1 :(得分:1)

在这里使用<str:article>Matches any non-empty string进行模式搜索,因此它也包含“搜索列表” ,因此路径wiki/searchlist将与{{1} }路径也。 urlpatterns 是一个列表,因此在迭代过程中,django将提供第一个匹配项,在您的情况下为wiki/<str:article>

wiki/<str:article>

因此,为了匹配除“ wiki /” 之后的“搜索列表” 以外的任何非空字符串,您需要在{{ 1}}

urlpatterns = [
    path("", views.index, name="index"),
    path("wiki/<str:article>", views.article, name='article'),
    path("wiki/searchlist", views.searchlist, name='search_list'),
]

现在要匹配wiki/<str:article>,Django将在列表中进一步查找,wiki/searchlist将找到与urlpatterns = [ path("", views.index, name="index"), path("wiki/searchlist", views.searchlist, name='search_list'), path("wiki/<str:article>", views.article, name='article'), ] 的第一个匹配项

答案 2 :(得分:0)

我根据Gaurav的建议得出了不完整的答案(如果可以的话,请贡献力量): “ search_list”和“ article”的路径均包含“ / wiki /”段。由于某种原因,即使我使用了HttpResponseRedirect(reverse(“ search_list”)),“文章”路径仍从“ wiki / searchlist”中抢夺了“ / searchlist”并将其作为字符串参数传递给其视图。

我仍然需要弄清楚为什么我的HttpResponseRedirect()调用被另一个视图劫持了。

相关问题