【问题标题】:Beginner having problems in Django with URLs初学者在 Django 中遇到 URL 问题
【发布时间】:2015-01-31 01:14:15
【问题描述】:

我正在尝试创建一个简单的 Todo 站点,允许您记录 todo 并将它们标记为已完成。我遇到的问题是网址。

当您第一次访问 localholst:8000/todo/ 时,一切都很好,它显示了我所有的待办事项。我现在希望能够选中旁边的复选框,并让列表自动更新,并删除该待办事项。当您从 localhost:8000/todo/ 执行此操作时,它工作正常 BUT 您留在 localhost:8000/todos/check/3 url 中(此 url 允许我通过正则表达式 url 捕获此视图以在单击时使用该待办事项更新数据库)。

问题:如果我随后单击另一个待办事项将其标记为已完成,则它不起作用。如果我尝试单击 id=4 的待办事项,我的 URL 是 localhost:8000/todos/check/3/check/4。您可以看到,在我这样做一次之后,它使用 url 来捕获更新数据库的视图,但它应该已经将用户发送回 localhost:8000/todo/ 以设置下一次检查。相反,它把我们留在了 localhost:8000/todos/check/3 并在其末尾添加了“/check/4”。

问题:在处理了对数据库的实际更新后,如何从 url 中丢失“check/3”?

我的主要 urls.py(指向我的 todo/urls.py 文件):

from django.conf.urls import patterns, include, url

urlpatterns = patterns('',
    url(r'^admin/', include(admin.site.urls)),
    url(r'^todo/', include("todo.urls", namespace="todo")),
)

我的 todo/urls.py 文件:

from django.conf.urls import patterns, url
from todo import views

urlpatterns = patterns('',                 
    url(r'^add/$', views.add, name='add'),
    url(r'^remove/$', views.remove_done, name='remove'),
    url(r'^check/(?P<todo_id>\d+)/$', views.check, name='check'),

    url(r'^$', views.index, name='index'),
)

views.py(截断)

from todo.models import todo

def index(request):
    todos_done = todo.objects.filter(done = True) # @UndefinedVariable
    todos_not_done = todo.objects.filter(done = False)
    total_todos = todos_done.count() + todos_not_done.count()

    return render(request, 'todo/index.html', { 'todos_done': todos_done, 'todos_not_done': todos_not_done, 'total': total_todos })

def check(request, todo_id):
    todo_to_mark = todo.objects.get(id=todo_id) # @UndefinedVariable

    if todo_to_mark.done == True:
        todo_to_mark.done = False
    else:
        todo_to_mark.done = True
    todo_to_mark.save()


    todos_done = todo.objects.filter(done = True)
    todos_not_done = todo.objects.filter(done = False)
    total_todos = todos_done.count() + todos_not_done.count()

    return render(request, 'todo/index.html', { 'todos_done': todos_done, 'todos_not_done': todos_not_done, 'total': total_todos })

最后,我的模板/todo/index.html 文件(截断)

    <div>
    <span>{{ todos_done|length }} of {{ total }} remaining</span>
    [ <a href="{% url 'todo:remove' %}">Clear all done</a> ]

    <ul class="unstyled">
        {% for todo in todos_done %}
            <li>
                <input type="checkbox" name="todo{{todo.id}}" id="{{todo.id}}" onchange="todoChecked({{todo.id}})" checked>
                <span class="done-true">{{ todo.todo_text }}</span>
            </li>
        {% endfor %}

        {% for todo in todos_not_done %}
            <li>
                <input type="checkbox" name="todo{{todo.id}}" id="{{todo.id}}" onchange="todoChecked({{todo.id}})" >
                <span>{{ todo.todo_text }}</span>
            </li>
        {% endfor %}
    </ul>

    <form action="{% url 'todo:add' %}" method="post">
    {% csrf_token %}
        <input type="text" size="30" name="new_text" id="new_text" placeholder="Add new todo here">
        <input class="btn-primary" type="submit" value="Add">
    </form>

    <!-- Javascript function -->
    <script>
        function todoChecked(todo_id) {
            window.open("../todo/check/" + todo_id); 
        }
    </script>
</div>

【问题讨论】:

  • 既然你把它放在模板中,你有../todo/check/,在javascript函数中,你可以使用Django的url模板标签。那,或者使用绝对路径,也应该可以解决问题,但是 catavaran 的答案是更好的解决方案。

标签: python django url


【解决方案1】:

我认为您只需按一下键即可。试试用点,而不是冒号:

<a href="{% url 'todo.remove' %}">Clear all done</a>

【讨论】:

  • 有一个todo命名空间,所以冒号是正确的。如果不是,则在尝试加载模板时会引发异常。
【解决方案2】:

您应该重定向回此列表,而不是在 check() 视图中呈现待办事项列表:

from django.shortcuts import get_object_or_404, render

def check(request, todo_id):
    todo_to_mark = get_object_or_404(todo, id=todo_id) # @UndefinedVariable
    todo_to_mark.done = not todo_to_mark.done
    todo_to_mark.save()
    return redirect('todo:index')

另外我建议使用get_object_or_404() 快捷方式来获取todo 对象。

【讨论】:

  • dylrei 的回答不起作用。 全部清除 我试过了。如果您查看 HTML 文件,您会看到以这种方式引用的其他 URL 确实有效,即。 {% url 'todo:add' %}。 Catavarans 的回答 return redirect('todo:index') 可以正常工作,但它会在浏览器中打开一个不可接受的新窗口。它应该只是重新加载同一页面。难道重定向是错误的调用方法吗?有没有不打开另一页的?
  • 在 javascript 中打开新窗口:window.open("../todo/check/" + todo_id)。我的回答只是解决了特定于 url 的问题。
  • 有没有办法让它在同一个窗口中打开。
  • 是的,window.location = "../todo/check/" + todo_id; 将在当前窗口中加载页面。
猜你喜欢
  • 1970-01-01
  • 2021-05-13
  • 2014-09-28
  • 1970-01-01
  • 1970-01-01
  • 2010-11-08
  • 2021-07-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多