Django能否不跳转页面从前端直接为Recipe模型的ingredients字段追加内容
这个功能完全可以实现,核心是用AJAX发送异步请求更新后端数据,不需要跳转页面。
实现步骤
1. 新增后端处理接口
首先在Django项目中新增专门处理添加配料请求的视图和路由:
视图代码(views.py)
from django.http import JsonResponse from django.shortcuts import get_object_or_404 from .models import Recipe def add_ingredient(request, recipe_slug): if not request.method == "POST": return JsonResponse({"status": "error", "msg": "请求方法错误"}, status=405) # 权限校验:仅允许修改当前登录用户自己的菜谱 recipe = get_object_or_404(Recipe, slug=recipe_slug, profile=request.user.profile) new_ingredient = request.POST.get("ingredient", "").strip() if not new_ingredient: return JsonResponse({"status": "error", "msg": "配料内容不能为空"}, status=400) # 追加配料,默认用换行分隔不同配料 if recipe.ingredients: recipe.ingredients += f"\n{new_ingredient}" else: recipe.ingredients = new_ingredient recipe.save() return JsonResponse({"status": "success", "msg": "配料添加成功"})
路由配置(urls.py)
urlpatterns = [ # 保留你原来的其他路由配置 path('add-ingredient/<slug:recipe_slug>/', views.add_ingredient, name='add_ingredient'), ]
2. 修改前端模板
先调整my_account页面的表格结构,增加配料输入区域,再插入JS逻辑处理异步请求:
{% for recipe in recipes %} <tr> <td><a href="{% url 'recipe_details' recipe.category.slug recipe.slug %}" class='field'>{{recipe.title}}</a></td> <!-- 新增配料输入区域 --> <td> <input type="text" class="ingredient-input" data-slug="{{ recipe.slug }}" placeholder="输入配料内容"> <button class="button is-small add-ingredient-btn">添加配料</button> </td> <td><a href="{% url 'update_recipe' recipe.slug %}" class='button is-dark'>Update</a></td> <td><a href="{% url 'delete_recipe' recipe.slug %}" class='button is-light'>Remove</a></td> </tr> {% endfor %} <!-- 页面底部添加JS处理逻辑 --> <script> // 获取Django CSRF Token,用于POST请求校验 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; } const csrftoken = getCookie('csrftoken'); // 监听所有添加配料按钮的点击事件 document.querySelectorAll('.add-ingredient-btn').forEach(btn => { btn.addEventListener('click', function() { const input = this.previousElementSibling; const recipeSlug = input.dataset.slug; const ingredientContent = input.value.trim(); if (!ingredientContent) { alert('请输入配料内容'); return; } // 发送异步请求 fetch(`/add-ingredient/${recipeSlug}/`, { method: 'POST', headers: { 'X-CSRFToken': csrftoken, 'Content-Type': 'application/x-www-form-urlencoded', }, body: `ingredient=${encodeURIComponent(ingredientContent)}` }) .then(res => res.json()) .then(data => { if (data.status === 'success') { alert(data.msg); input.value = ''; // 添加成功后清空输入框 } else { alert(data.msg); } }) .catch(err => { alert('添加失败,请重试'); console.error(err); }) }) }) </script>
注意事项
- 示例中配料默认用换行符分隔,你可以根据需要改成逗号、分号等其他分隔符
- 代码默认用户登录后
request.user关联了对应的Profile模型,如果你的权限逻辑不同,可以自行调整视图中的校验规则 - 生产环境建议对用户输入的配料内容做合法性校验,过滤敏感字符,避免XSS安全风险
内容的提问来源于stack exchange,提问作者mohammed shajahan
相关产品推荐
相关产品推荐

