如何在同一Django模板页面中保留两个表单的数据?
Django共用模板时用户资料为空问题修复
问题描述
Django项目中,ProfileUpdateView和UserDeleteView共用profile.html模板。当访问ProfileUpdateView的GET/POST请求时,用户资料数据正常显示;但向UserDeleteView发送POST请求且未勾选accountActivation复选框时,页面虽能渲染,但上方的用户资料区域为空。
相关代码
urls.py
from django.contrib import admin from django.urls import include, path from apps.iam.views import ProfileUpdateView, UserDeleteView urlpatterns = [ path("accounts/profile", ProfileUpdateView, name="profile_detailupdate"), path("accounts/delete", UserDeleteView, name="user_delete"), ]
views.py
import zoneinfo from django.contrib.auth import get_user_model from django.contrib.auth import logout as auth_logout from django.contrib.auth.decorators import login_required from django.shortcuts import HttpResponseRedirect, get_object_or_404, render from django.utils import timezone from django.views.decorators.http import require_http_methods from django.views.generic import TemplateView, UpdateView from .forms import ProfileForm from .models import Profile User = get_user_model() # Homepage class HomeDetailView(TemplateView): template_name = "home.html" # Profile ## Update @login_required @require_http_methods(["GET","POST"]) def ProfileUpdateView(request): # dictionary for initial data with field names as keys context = {} # fetch the object related to passed id profile_object = get_object_or_404(Profile, id=request.user.id) # pass the object as instance in form profile_form = ProfileForm(request.POST or None, instance=profile_object) # save the data from the form if profile_form.is_valid(): profile_form.save() # add form dictionary to context context["profile_form"] = profile_form # activate the new timezone in case changed request.session["django_timezone"] = request.user.profile.timezone timezone.activate(zoneinfo.ZoneInfo(request.user.profile.timezone)) return render(request, "profile.html", context) ## Delete @login_required @require_http_methods(["POST"]) def UserDeleteView(request): # dictionary for initial data with field names as keys context = {} # fetch the object related to passed id user_object = get_object_or_404(Profile, id=request.user.id) # pass the object as instance in form userdelete_form = ProfileForm(request.POST or None, instance=user_object) # add form dictionary to context context["userdelete_form"] = userdelete_form # user verified account deletion if request.POST.get("accountActivation") == "on": User = get_user_model() user_pk = request.user.pk auth_logout(request) User.objects.filter(pk=user_pk).delete() return render(request, "home.html", context) else: return render(request, "profile.html", context)
profile.html
{% extends 'base.html' %} {% load static %} {% load widget_tweaks %} {% block head_title %} {{ title }} {% endblock %} {% block body %} <div class="container-xxl flex-grow-1 container-p-y"> <div class="row"> <div class="col-md-12"> <div class="card mb-4"> <h5 class="card-header">Profile Details</h5> <!-- Account --> <div class="card-body"> <div class="d-flex align-items-start align-items-sm-center gap-4"> <img src="{% static 'img/avatars/1.png' %}" alt="user-avatar" class="d-block rounded" height="100" width="100" id="uploadedAvatar" /> <div class="button-wrapper"> <label for="upload" class="btn btn-primary me-2 mb-4" tabindex="0"> <span class="d-none d-sm-block">Upload new photo</span> <i class="bx bx-upload d-block d-sm-none"></i> <input type="file" id="upload" class="account-file-input" hidden accept="image/png, image/jpeg" /> </label> <button type="button" class="btn btn-outline-secondary account-image-reset mb-4"> <i class="bx bx-reset d-block d-sm-none"></i> <span class="d-none d-sm-block">Reset</span> </button> <p class="text-muted mb-0">Allowed JPG, GIF or PNG. Max size of 800K</p> </div> </div> </div> <hr class="my-0" /> <div class="card-body"> <form id="formAccountSettings" method="POST" action="{% url 'profile_detailupdate' %}"> <!-- Security token by Django --> {% csrf_token %} <!-- form --> {% for hidden in profile_form.hidden_fields %} {{ hidden }} {% endfor %} <div class="row"> {% for field in profile_form.visible_fields %} <div class="mb-3 col-md-6"> <label for="{{ field.id_for_label }}">{{ field.label }}</label> {% if field.field.widget.input_type == "select" %} {{ field|add_class:'form-control form-select' }} {% else %} {{ field|add_class:'form-control' }} {% endif %} {% for error in field.errors %} <span class="help-block">{{ error }}</span> {% endfor %} </div> {% endfor %} <div class="mt-2"> <button name="profile" type="submit" class="btn btn-primary me-2">Save changes</button> <button type="reset" class="btn btn-outline-secondary">Cancel</button> </div> </form> </div> <!-- /Account --> </div> <div class="card"> <h5 class="card-header">Delete Account</h5> <div class="card-body"> <div class="mb-3 col-12 mb-0"> <div class="alert alert-warning"> <h6 class="alert-heading fw-bold mb-1">Are you sure you want to delete your account?</h6> <p class="mb-0">Once you delete your account, there is no going back. Please be certain.</p> </div> </div> <form id="formAccountDeactivation" method="POST" action="{% url 'user_delete' %}"> <!-- Security token by Django --> {% csrf_token %} <!-- form --> {% for hidden in deleteuser_form.hidden_fields %} {{ hidden }} {% endfor %} <div class="form-check mb-3"> <input class="form-check-input" type="checkbox" name="accountActivation" id="accountActivation" /> <label class="form-check-label" for="accountActivation">I confirm my account deactivation</label> </div> <button name="delete" type="submit" class="btn btn-danger deactivate-account">Deactivate Account</button> </form> </div> </div> </div> </div> </div> {% endblock %}
问题原因
- 上下文变量缺失:
UserDeleteView返回profile.html时,上下文仅传入了userdelete_form,但模板渲染用户资料区域依赖的是profile_form变量,导致模板无法找到该变量,资料区域为空。 - 模板变量名不匹配:模板中删除表单部分使用了
deleteuser_form变量,但视图中传入的变量名为userdelete_form,存在拼写差异。
修复方案
1. 修改UserDeleteView,添加profile_form到上下文
更新UserDeleteView函数,在返回profile.html前,创建profile_form并传入上下文,确保模板能渲染用户资料:
@login_required @require_http_methods(["POST"]) def UserDeleteView(request): context = {} # 准备profile_form,供模板渲染用户资料区域 profile_object = get_object_or_404(Profile, id=request.user.id) profile_form = ProfileForm(instance=profile_object) context["profile_form"] = profile_form # 处理删除表单逻辑 user_object = get_object_or_404(Profile, id=request.user.id) userdelete_form = ProfileForm(request.POST or None, instance=user_object) context["userdelete_form"] = userdelete_form if request.POST.get("accountActivation") == "on": User = get_user_model() user_pk = request.user.pk auth_logout(request) User.objects.filter(pk=user_pk).delete() return render(request, "home.html", context) else: return render(request, "profile.html", context)
2. 修正模板中删除表单的变量名
将profile.html中删除表单部分的deleteuser_form改为userdelete_form,匹配视图传入的变量名:
<!-- 修改前 --> {% for hidden in deleteuser_form.hidden_fields %} {{ hidden }} {% endfor %} <!-- 修改后 --> {% for hidden in userdelete_form.hidden_fields %} {{ hidden }} {% endfor %}
内容的提问来源于stack exchange,提问作者bigredthelogger
相关产品推荐
相关产品推荐

