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

Django中UpdateView无法正常更新的问题求助

Django UpdateView提交后触发添加视图逻辑的问题排查

我正在开发一个流媒体平台风格的Django项目用于作品集展示,在影片数据库管理模块(实现影片增删改)中,使用UpdateView更新影片信息时遇到问题:

  • 编辑页面能正常访问,表单也正确加载了影片原有信息
  • 点击保存后,却触发了添加影片的ManageFilmsView里的提示:"This film is already in the database"
  • 目前看起来提交请求后被重定向到了添加视图,试图创建新条目,和UpdateView的预期功能不符

想明确保存按钮的提交逻辑,是否需要重写UpdateView的方法?接下来该做哪些排查?


相关代码

Views代码

class ManageFilmsView(FormView, ListView):
    model = Film
    template_name = "manage-films.html"
    context_object_name = "films"
    form_class = AddFilmForm
    success_url = reverse_lazy("manage_films")

    def get_queryset(self):
        parameter = self.kwargs.get("letter") if self.kwargs.get("letter") else "a"
        return Film.objects.filter(title__startswith=parameter)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        letters = list(string.ascii_uppercase)
        context["letters"] = letters
        context["selected_letter"] = (
            self.kwargs.get("letter") if self.kwargs.get("letter") else "a"
        )
        return context

    def form_valid(self, form):
        search_title = form.cleaned_data["title"].replace(" ", "+")
        search_year = form.cleaned_data["year"]
        response = requests.get(
            f"http://www.omdbapi.com/?apikey={api_key}&t={search_title}&y={search_year}"
        )
        response.raise_for_status()
        film_data = response.json()

        if Film.objects.filter(title=film_data["Title"]).exists():
            messages.add_message(
                self.request,
                messages.INFO,
                f"This film is already present in the database.",
            )
        else:
            film = Film(
                title=film_data["Title"],
                year=film_data["Year"],
                genre=film_data["Genre"],
                country=film_data["Country"],
                director=film_data["Director"],
                actors=film_data["Actors"],
                runtime=film_data["Runtime"],
                poster=film_data["Poster"],
                plot=film_data["Plot"],
            )
            film.save()
            messages.add_message(
                self.request,
                messages.SUCCESS,
                f"{ film.title } successfully added to the database.",
            )
        return HttpResponseRedirect(self.get_success_url())

    def form_invalid(self, form):
        messages.add_message(self.request, messages.ERROR, "Something went wrong.")
        return HttpResponseRedirect(self.get_success_url())


class FilmsListView(ListView):
    model = Film
    context_object_name = "films"
    template_name = "manage-films-list.html"

    def get_queryset(self):
        parameter = self.kwargs.get("letter") if self.kwargs.get("letter") else "a"
        return Film.objects.filter(title__startswith=parameter)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        letters = list(string.ascii_uppercase)
        context["letters"] = letters
        context["selected_letter"] = (
            self.kwargs.get("letter") if self.kwargs.get("letter") else "a"
        )
        return context


class FilmEditView(UpdateView):
    model = Film
    fields = [
        "title",
        "year",
        "genre",
        "country",
        "director",
        "actors",
        "runtime",
        "poster",
        "trailer",
        "plot",
        "why",
    ]
    template_name = "edit-film.html"
    success_url = reverse_lazy("films_list")

URLs代码

urlpatterns = [
    path("", ManageFilmsView.as_view(), {"letter": None}, name="manage_films"),
]

htmxpatterns = [
    path("<str:letter>", FilmsListView.as_view(), name="films_list"),
    path("edit/<int:pk>", FilmEditView.as_view(), name="edit_film"),
    path("delete/<int:pk>", DeleteFilmView.as_view(), name="delete_film"),
]

urlpatterns += htmxpatterns

编辑页面模板(简化版)

{% load widget_tweaks %}

<h2 class="text-xl my-4 ml-10 p-4">Here are the details to edit the informations about the film "{{ film.title }}"</h2>
<form action="" action="" class="w-3/5 ml-10 flex flex-col" method="POST">  
    {% csrf_token %}  
    <div class="mb-4">
        <label class="mb-1 text-gray-100">{{ form.title.label|upper }}</label>
        {% render_field form.title class="bg-gray-50 border border-gray-300 text-gray-950 text-lg rounded-lg block w-full p-2.5 dark:bg-gray-600 dark:border-gray-500 dark:placeholder-gray-400 dark:text-white" %}
    </div>
    <div class="mb-4">
        <label class="mb-1 text-gray-100">{{ form.genre.label|upper }}</label>
        {% render_field form.genre class="bg-gray-50 border border-gray-300 text-gray-950 text-lg rounded-lg block w-full p-2.5 dark:bg-gray-600 dark:border-gray-500 dark:placeholder-gray-400 dark:text-white" %}
    </div>
    <button type="submit" value="Update" class="w-1/4 mt-2 mb-20 text-gray-100 bg-gray-900 hover:bg-gray-950 dark:bg-gray-600 dark:hover:bg-red-900 font-medium rounded-lg text-sm px-5 py-2.5 text-center place-items-center">SAVE</button>  
</form>

问题排查与修复方案

核心原因分析

  1. 表单提交路径错误
    模板里的form标签写了两个重复的action="",虽然浏览器会忽略重复属性,但空action可能导致请求提交到错误的路径(比如父页面的manage_films路径),从而触发添加视图的逻辑。
  2. URL路由匹配优先级
    主路由的空路径""会匹配所有未被更具体路由捕获的请求,如果表单提交路径有误,会直接触发ManageFilmsView。

具体排查步骤

  • 检查请求路径:打开浏览器开发者工具的Network面板,提交表单时查看POST请求的Request URL,确认是否指向/edit/[影片ID]。如果不是,说明表单action存在问题。
  • 修复表单action:把模板里的重复action=""替换为明确的路由指向:action="{% url 'edit_film' film.pk %}",确保请求提交到UpdateView的正确路径。
  • 验证UpdateView独立功能:直接访问/edit/[影片ID]并提交表单,观察是否触发更新逻辑,排除路由或中间件的干扰。
  • 添加调试日志:在FilmEditView和ManageFilmsView的form_valid方法中添加打印语句,确认哪个视图被触发,进一步定位问题。

关键代码修复

修改编辑页面的表单action:

{% load widget_tweaks %}

<h2 class="text-xl my-4 ml-10 p-4">编辑影片 "{{ film.title }}" 的信息</h2>
<form action="{% url 'edit_film' film.pk %}" class="w-3/5 ml-10 flex flex-col" method="POST">  
    {% csrf_token %}  
    <!-- 表单字段保持不变 -->
    <button type="submit" class="w-1/4 mt-2 mb-20 text-gray-100 bg-gray-900 hover:bg-gray-950 dark:bg-gray-600 dark:hover:bg-red-900 font-medium rounded-lg text-sm px-5 py-2.5 text-center place-items-center">保存</button>  
</form>

如果需要验证UpdateView的执行情况,可以重写form_valid添加提示:

class FilmEditView(UpdateView):
    # 原有属性保持不变
    def form_valid(self, form):
        messages.add_message(self.request, messages.SUCCESS, f"{self.object.title} 信息更新成功")
        return super().form_valid(form)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 07:29:51