如何通过JavaScript实现模型URLField(Instagram)的无刷新更新
问题描述
我有一个展示网站管理员信息(用户名、技能、Instagram主页、个人简介)的页面,管理员可通过JavaScript的fetch API编辑并保存个人资料。点击保存按钮后,除了URL类型的Instagram字段外,其余信息均可实时更新,该字段必须刷新页面才能生效。控制台日志显示所有操作均正常,请问如何实现该字段的无刷新更新?
相关代码
about.js
document.addEventListener("DOMContentLoaded", function(){ const button = document.querySelectorAll("#edit_profile") button.forEach(function(button){ button.onclick = function(){ // 补充获取当前成员ID const memberID = this.dataset.id; const username = document.getElementById(`username_${memberID}`); const skills = document.getElementById(`skills_${memberID}`); const bio = document.getElementById(`bio_${memberID}`); // 保存Instagram链接的DOM元素引用,而非仅存href值 const instagramLink = document.getElementById(`instagram_${memberID}`); var instagram = instagramLink.href; let edit_username = document.createElement("textarea"); edit_username.setAttribute("rows", "1"); edit_username.innerHTML = username.innerHTML edit_username.id = `edit_username_${memberID}`; edit_username.className = `form-control username`; let edit_skills = document.createElement("textarea"); edit_skills.setAttribute("rows","1"); edit_skills.innerHTML = skills.innerHTML; edit_skills.id = `edit_skills_${memberID}`; edit_skills.className = "form-control"; let edit_bio = document.createElement("textarea"); edit_bio.setAttribute("rows","3"); edit_bio.innerHTML = bio.innerHTML; edit_bio.id = `edit_bio_${memberID}`; edit_bio.className = "form-control"; let edit_instagram = document.createElement("textarea"); edit_instagram.setAttribute("rows","1"); edit_instagram.innerHTML = instagram; edit_instagram.id = `edit_instagram_${memberID}`; edit_instagram.className = "form-control social-media"; const saveButton = document.createElement("button"); saveButton.innerHTML = "Save"; saveButton.id = `saveButton_${memberID}`; saveButton.className = "btn btn-success col-3"; saveButton.style.margin = "10px"; const editContainer = document.getElementById(`edit_${memberID}`); // 清空容器避免重复生成编辑控件 editContainer.innerHTML = ""; editContainer.append(edit_username); editContainer.append(edit_skills); editContainer.append(edit_bio); editContainer.append(edit_instagram); editContainer.append(saveButton); // 保存按钮点击事件 saveButton.addEventListener("click", function(){ edit_username = document.getElementById(`edit_username_${memberID}`); edit_skills = document.getElementById(`edit_skills_${memberID}`); edit_bio = document.getElementById(`edit_bio_${memberID}`); edit_instagram = document.getElementById(`edit_instagram_${memberID}`); fetch(`/edit_profile/${memberID}`,{ method: "POST", headers: { 'Content-Type': 'application/json', // 补充Django需要的CSRF令牌 'X-CSRFToken': getCookie('csrftoken') }, body: JSON.stringify({ username: edit_username.value, skills: edit_skills.value, instagram: edit_instagram.value, bio: edit_bio.value, itch_profile: document.getElementById(`itch_${memberID}`).href }) }) .then(response => response.json()) .then(result => { console.log(result); if(result.error){ // 取消编辑,清空容器 editContainer.innerHTML = ""; } else { // 更新普通文本字段 username.innerHTML = result.username; document.getElementById(`secusername_${memberID}`).innerHTML = `${result.username}, `; skills.innerHTML = result.skills; bio.innerHTML = result.bio; // 核心:直接更新Instagram链接的href属性 instagramLink.href = result.instagram; // 清空编辑容器 editContainer.innerHTML = ""; } }) .catch(error => console.error('保存失败:', error)); }) } }); }); // 辅助函数:获取Django CSRF令牌 function getCookie(name) { let cookieValue = null; if (document.cookie && document.cookie !== '') { const cookies = document.cookie.split(';'); for (let i = 0; i < cookies.length; i++) { const cookie = cookies[i].trim(); if (cookie.substring(0, name.length + 1) === (name + '=')) { cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); break; } } } return cookieValue; }
about.html
{% for member in team_members %} <div class="col" id="border"> <!--管理员可见编辑按钮--> {% if user.is_superuser %} <div class="position-relative" id="edit_button_{{member.id}}" style="display: block;"> <button class="btn btn-lg position-absolute top-0 end-0" id="edit_profile" data-id="{{member.id}}" data-username="{{member.username}}"> <i class="fa fa-edit fa-solid" style="color: white; margin-right: 5px;"></i></button> </div> {% endif %} <!--编辑表单容器--> <div class="form-group" id="edit_{{member.id}}"> </div> <!--展示用户信息--> <div id="remove_{{member.id}}" style="display: block;"> <h3 class="username" id="username_{{member.id}}">{{member.username}}</h3> <p class ="skills" id="skills_{{member.id}}">{{member.skills}}</p> <p><a class="social-media" href="{{member.instagram}}" id="instagram_{{member.id}}"><i class="fa-brands fa-instagram fa-solid" style="color: #e3c142; margin-right: 5px;"></i></a> <a class="social-media" href="{{member.itch_profile}}" id="itch_{{member.id}}"><i class="fa-brands fa-itch-io" style="color: #e3c142;"></i></a> <div class="bio"> <strong class="username" id="secusername_{{member.id}}" style="font-size: large;">{{member.username}}, </strong><p id="bio_{{member.id}}">{{member.bio}}</p> </div> </div> </div> </div> {% endfor %}
views.py
from django.http import JsonResponse from django.views.decorators.csrf import csrf_exempt import json from .models import Team @csrf_exempt def edit_profile(request, member_id): if request.method != "POST": return JsonResponse({"error": "仅支持POST请求。"}, status=400) try: team_member = Team.objects.get(id=member_id) except Team.DoesNotExist: return JsonResponse({"error": "用户不存在。"}, status=404) try: body_unicode = request.body.decode('utf-8') body = json.loads(body_unicode) except json.JSONDecodeError: return JsonResponse({"error": "无效的JSON数据。"}, status=400) # 安全获取字段值,避免KeyError username = body.get('username', team_member.username) skills = body.get('skills', team_member.skills) instagram = body.get('instagram', team_member.instagram) itch_profile = body.get('itch_profile', team_member.itch_profile) bio = body.get('bio', team_member.bio) # 更新数据库 Team.objects.filter(id=member_id).update( username=username, skills=skills, instagram=instagram, itch_profile=itch_profile, bio=bio ) return JsonResponse({ "message": "保存成功", "username": username, "skills": skills, "instagram": instagram, "itch_profile": itch_profile, "bio": bio }, status=200)
解决方案
问题核心是你之前只更新了存储URL的变量,没有修改页面上<a>标签的href属性:
- 保存DOM元素引用:在编辑按钮点击时,获取Instagram链接的DOM元素(
const instagramLink = document.getElementById(\instagram_${memberID}`);),而不是仅提取href`值。 - 直接修改href属性:在fetch请求成功的回调里,执行
instagramLink.href = result.instagram;,这样就能实时更新链接地址,无需刷新页面。
另外补充了两个原代码的潜在问题:
- 添加了Django必需的CSRF令牌验证,避免请求被拦截。
- 每次编辑前清空编辑容器,防止重复生成编辑控件。
内容的提问来源于stack exchange,提问作者user17470872
相关产品推荐
相关产品推荐

