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

Django+HTMX实现可编辑行时出现NoReverseMatch错误求助

Django + HTMX 可编辑行触发NoReverseMatch错误

我用Django搭配HTMX实现链接列表的可编辑行功能,点击行内编辑按钮时出现django.urls.exceptions.NoReverseMatch错误,具体提示:

Reverse for 'link_update' with keyword arguments '{'pk': ''}' not found. 1 pattern(s) tried: ['link/edit/(?P[0-9]+)/\Z']

试过Stack Overflow上的多种方法仍未解决,相关代码如下:

项目根目录urls.py

urlpatterns = [
    path('', home, name='home'),
    path('admin/', admin.site.urls),
    path("user/", include("user_profile.urls", namespace="user")),
    path("link/", include("link.urls", namespace='link')),
]

link应用下的urls.py

from django.urls import path
from link.views import tag_view, category_view, delete_links, delete_link, get_row_view, LinkUpdateView, LinkyListView


app_name = 'link'

urlpatterns = [
    path('edit/<int:pk>/', LinkUpdateView.as_view(), name='link_update'),
    path('edit/<int:pk>/get_row_view/', get_row_view, name='get_row_view'),
    path('tag/<slug:tag_slug>/', tag_view, name='tag_view'),
    path('category/<slug:category_slug>/', category_view, name='category_view'),
    path('delete/', delete_links, name='delete_links'),
    path('delete-item/<int:pk>/', delete_link, name='delete_link'),
    path('list', LinkyListView.as_view(), name='link_list_view'),
]

link应用下的views.py

def get_row_view(request, pk):
    link = LinkUrl.objects.get(pk=pk)
    context = dict(
        link=link,
    )
    return render(request, 'link/row.html', context)

class LinkUpdateView(UpdateView):
    model = LinkUrl
    form_class = LinkModelForm
    template_name = 'link/edit_link_form.html'

    def get_success_url(self):
        return reverse_lazy('link:link_update', kwargs={'pk': self.object.pk})

row.html

<tr id="link_list_{{link.pk}}">
    <td>{{ link.title }}</td>
    <td>{{ link.get_full_url }}</td>
    <td>  
      <span class="p-1 border fs-12 rounded text-light bg-primary">
        <a href="{{ link.category.get_absolute_url }}" class="text-decoration-none text-light">
          {{ link.category }}
        </a>
      </span>
    </td>
    <td>   
        {% for shortcode, tags in tags_by_shortcode.items %}
        {% if shortcode == link.shortcode %}
          {% for tag in tags %}
            <li class="list-inline-item border p-1 text-muted fs-12 mb-1 rounded">
              <a href="{{ tag.get_absolute_url }}" class="text-decoration-none text-muted">
                {{ tag.title }}
              </a>
            </li>
          {% endfor %}
        {% endif %}
      {% endfor %}
    </td>

    <td>
        <button class="btn btn-warning" 
        hx-get="{% url 'link:link_update' pk=link.pk %}"
        hx-target="#link_list_{{link.pk}}">
        Edit
        </button>
    </td>
    <td>
        <button
        class="btn btn-danger btn-sm float-end"
        hx-delete="{% url 'link:delete_link' link.pk %}"
        hx-confirm="Are you sure you want to delete this item?"
        hx-target="#link_list_{{link.id}}"
        hx-swap="outerHTML"> Delete
        </button>    
      </td>
  </tr>
<td>
    <form hx-post="{% url 'link:link_update' pk=link.pk %}">
        {% csrf_token %}
          {% load crispy_forms_tags %}
         
          {% for field in form %}
               <td colspan="{{ form|length }}">
                    <div class="form-row">
                    <div class="form-group col-md-12">
                    {{ field|as_crispy_field }}
                    </div>
                    </div>
                </td>    
          {% endfor %}
        <td>
            <button class="btn btn-primary" type="submit" hx-get="{% url 'link:get_row_view' pk=link.pk %}" hx-target="#form-container"> Save </button>   
        </td>
        <td>
            <button class="btn btn-danger" type="button">Cancel</button>
        </td>
    </form>
</td>

问题排查与修复

错误核心是模板渲染时pk参数为空,导致URL反转失败,针对性修复如下:

  1. 修正EditForm的上下文变量
    Django的UpdateView默认将当前对象以object或小写模型名(linkurl)传入上下文,而非link。所以edit_link_form.html里的link.pk取不到值,导致URL反转时pk为空。
  • 方案一:把edit_link_form.html中所有link.pk替换为object.pk
  • 方案二:在LinkUpdateView中手动添加link到上下文:
    class LinkUpdateView(UpdateView):
        # 原有代码保留
        def get_context_data(self, **kwargs):
            context = super().get_context_data(**kwargs)
            context['link'] = self.object
            return context
    
  1. 调整保存后的跳转逻辑
    当前get_success_url返回编辑页面本身,不符合HTMX交互逻辑,应该返回更新后的行HTML:
def get_success_url(self):
    return reverse_lazy('link:get_row_view', kwargs={'pk': self.object.pk})

同时修改edit_link_form.html的提交按钮,让HTMX直接替换目标行:

<button class="btn btn-primary" type="submit" hx-target="#link_list_{{object.pk}}" hx-swap="outerHTML"> Save </button>
  1. 统一模板中的ID引用
    row.html里tr的ID是link_list_{{link.pk}},但删除按钮的hx-target用了link_list_{{link.id}},建议统一为link.pk避免潜在问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 11:47:12