英文:
Django: How to use a modal to delete an object?
问题
在我提供的翻译中,我只会返回代码的翻译部分,不包括问题的回答或额外的内容。
在索引页面上,我包含了一个按钮来删除一个未使用的食物对象。删除按钮启动了一个基于Bootstrap 5的模态删除表单。但是当我点击删除按钮时,错误信息中包含了索引页面的名称。在下面的代码中,可以在哪里和如何修复这个问题?
期望的删除URL:.../food/1/delete
页面未找到:Request URL: http://127.0.0.1:8000/food/foodIndex/1/delete
值得注意的是,404错误将请求视为GET
而不是POST
。
food/urls.py:
urlpatterns = [
path('foodIndex/', views.foodIndex, name="foodIndex"),
path('<int:id>/edit/', views.foodEdit, name="foodEdit"),
path('<int:id>/foodDelete/', views.foodDelete, name="foodDelete")
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
注意:path('foodIndex/<int:id>/foodDelete/', ...
不能解决这个问题。
在“.../food/foodIndex.html”中包含的模板部分:
{% if allFoods.count > 0 %}
{% for food in allFoods %}
<tr>
<td data-foodid="{{ food.id }}">{{ food }}</td>
<td><a class="btn p-0" href='{% url "food:foodEdit" food.id %}'>Edit</a></td>
{% if food.used == False %}
<td><button id='btn_delete' type="button" class="btn p-0" data-bs-toggle="modal" data-bs-target="#modal-delete" data-bs-foodid='{{ food.id }}' data-bs-foodname='{{ food }}'>Delete</button></td>
{% endif %}
</tr>
{% endfor %}
{% else %}
<tr>
<td colspan="3">no records found</td>
</tr>
{% endif %}
“.../food/foodIndex.html”中的模态框部分:
<div id="modal-delete" class="modal fade" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Delete food item</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<form >
<button id='food-delete' class="btn btn-warning" type="submit">Delete</button>
</form>
</div>
</div>
</div>
</div>
删除表单部分:
{<form method="POST" action="{% url 'food:foodDelete' pk=food.id %}" onsubmit="return confirm('Are you sure you want to delete this item?');">
<button class="btn">Delete</button>
</form>}
用于模态框的JavaScript部分:
const deleteModal = document.getElementById('modal-delete');
deleteModal.addEventListener('show.bs.modal', event => {
const button = event.relatedTarget
const foodName = button.getAttribute('data-bs-foodname')
const foodId = button.getAttribute('data-bs-foodid')
const modalBodyInput = deleteModal.querySelector('.modal-body ')
const modalFooterButtons= deleteModal.querySelector('form')
modalBodyInput.textContent = `Confirm deletion of ${foodName}`
modalFooterButtons.setAttribute('action',`${foodId}/delete`)
});
英文:
On the index page for a list of food objects I've included a button to delete an object that is not used. The delete button launches a Bootstrap 5 modal delete form. But when I click the Delete button, the error thrown includes the name of index page. In the code below, where & how can this be fixed?
Expected url on delete: .../food/1/delete
Page not found: Request URL: http://127.0.0.1:8000/food/foodIndex/1/delete
It may be worth noting that the 404 error considers the request to be GET
rather than POST
[I'm attempting to learn Python & Django by recreating a working PHP project. All of the HTML & javascript comes from that project.]
food/urls.py:
urlpatterns = [
path('foodIndex/', views.foodIndex, name="foodIndex"),
path('<int:id>/edit/', views.foodEdit, name="foodEdit"),
path('<int:id>/foodDelete/', views.foodDelete, name = "foodDelete")
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
Note: a path('foodIndex/<int:id>/foodDelete/',...
does not solve the problem
Template included in ".../food/foodIndex.html":
{% if allFoods.count > 0 %}
{% for food in allFoods %}
<tr>
<td data-foodid="{{ food.id }}">{{ food }}</td>
<td><a class="btn p-0" href='{% url "food:foodEdit" food.id %}'>Edit</a></td>
{% if food.used == False %}
<td><button id='btn_delete' type="button" class="btn p-0" data-bs-toggle="modal" data-bs-target="#modal-delete" data-bs-foodid='{{ food.id }}' data-bs-foodname='{{ food }}'>Delete</button></td>
{% endif %}
</tr>
{% endfor %}
{% else %}
<tr>
<td colspan="3">no records found</td>
</tr>
{% endif %}
Modal in ".../food/foodIndex.html":
<div id="modal-delete" class="modal fade" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Delete food item</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<form >
<button id='food-delete' class="btn btn-warning" type="submit">Delete</button>
</form>
</div>
</div>
</div>
</div>
delete form:
{<form method="POST" action="{% url 'food:foodDelete' pk=food.id %}" onsubmit="return confirm('Are you sure you want to delete this item?');">
<button class="btn">Delete</button>
</form>}
javascript for modal:
const deleteModal = document.getElementById('modal-delete');
deleteModal.addEventListener('show.bs.modal', event => {
const button = event.relatedTarget
const foodName = button.getAttribute('data-bs-foodname')
const foodId = button.getAttribute('data-bs-foodid')
const modalBodyInput = deleteModal.querySelector('.modal-body ')
const modalFooterButtons= deleteModal.querySelector('form')
modalBodyInput.textContent = `Confirm deletion of ${foodName}`
modalFooterButtons.setAttribute('action',`${foodId}/delete`)
}
);
答案1
得分: 0
问题出在您构建URL的方式上。
deleteModal.addEventListener('show.bs.modal', event => {
...
modalFooterButtons.setAttribute('action',`${foodId}/delete`)
});
这将始终只产生 some-id/delete
作为您的操作,您没有构建完整的路径。一个简单的解决方案是使用 DTL
来构建您的 URL
,使用 reverse resolution
,就像在您的 delete form
代码块中一样。
但是,可以将其作为表格删除按钮的属性使用(可以直接替换 data-bs-foodid
)。
<button
id='btn-delete'
class="btn-warning"
data-bs-toggle="modal"
data-bs-target="#modal-delete"
data-bs-foodname='{{ food }}'
data-bs-url="{% url 'food:foodDelete' food.id %}"
>
Delete
</button>
然后,我们使用相同的JavaScript方法检索它并在表单上设置这些值。
deleteModal.addEventListener('show.bs.modal', event => {
...
const deleteForm = deleteModal.querySelector('form');
const url = button.getAttribute('data-bs-url');
deleteForm.setAttribute('action', url);
deleteForm.setAttribute('method', 'post');
});
全面示例:
foodIndex.html(带有食物的表格)
<table class="table">
<thead>
<tr>
<th scope="col">Name</th>
<th scope="col" colspan="2">Actions</th>
</tr>
</thead>
<tbody>
{% if allFoods.count > 0 %}
{% for food in allFoods %}
<tr>
<th scope="row">{{food.name}}</th>
<td><button>Edit</button></td>
<td>
<button
id='btn-delete'
class="btn-warning"
data-bs-toggle="modal"
data-bs-target="#modal-delete"
data-bs-foodname='{{ food }}'
data-bs-url="{% url 'food:foodDelete' food.id %}"
>
Delete
</button>
</td>
</tr>
{% endfor %}
{% else %}
<tr>
<td colspan="3">no records found</td>
</tr>
{% endif %}
</tbody>
</table>
foodIndex.html(Modal - 注意 {% csrf_token %}
)
<div id="modal-delete" class="modal fade" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Delete food item</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<form>
{% csrf_token %}
<button id='food-delete' class="btn btn-danger" type="submit">Delete</button>
</form>
</div>
</div>
</div>
</div>
foodIndex.html(脚本)
<script>
const deleteModal = document.getElementById('modal-delete');
deleteModal.addEventListener('show.bs.modal', event => {
const button = event.relatedTarget;
const foodName = button.getAttribute('data-bs-foodname');
const url = button.getAttribute('data-bs-url');
const modalBodyInput = deleteModal.querySelector('.modal-body ');
modalBodyInput.textContent = `Confirm deletion of ${foodName}`;
const deleteForm = deleteModal.querySelector('form');
deleteForm.setAttribute('action', url);
deleteForm.setAttribute('method', 'post');
});
</script>
<details>
<summary>英文:</summary>
The problem is in the form on how you are building your URL.
```JavaScript
deleteModal.addEventListener('show.bs.modal', event => {
...
modalFooterButtons.setAttribute('action',`${foodId}/delete`)
}
);
That will always yield just some-id/delete
as your action, you are not building the full path. One simple solution would be to use DTL
to build your URL
using reverse resolution
, just like in your delete form
code block.
But, instead, use that as an attribute of the table delete button (you can just replace data-bs-foodid
)
<button
id='btn-delete'
class="btn-warning"
data-bs-toggle="modal"
data-bs-target="#modal-delete"
data-bs-foodname='{{ food }}'
data-bs-url="{% url 'food:foodDelete' food.id %}"
>
Delete
</button>
Then, we retrieve it and set those values on the form using the same method with JavaScript:
deleteModal.addEventListener('show.bs.modal', event => {
...
const deleteForm= deleteModal.querySelector('form');
const url = button.getAttribute('data-bs-url');
deleteForm.setAttribute('action', url);
deleteForm.setAttribute('method', 'post');
});
<h2>Full example</h2>
foodIndex.html (Table with Foods)
<table class="table">
<thead>
<tr>
<th scope="col">Name</th>
<th scope="col" colspan="2">Actions</th>
</tr>
</thead>
<tbody>
{% if allFoods.count > 0 %}
{% for food in allFoods %}
<tr>
<th scope="row">{{food.name}}</th>
<td><button>Edit</button></td>
<td>
<button
id='btn-delete'
class="btn-warning"
data-bs-toggle="modal"
data-bs-target="#modal-delete"
data-bs-foodname='{{ food }}'
data-bs-url="{% url 'food:foodDelete' food.id %}"
>
Delete
</button>
</td>
</tr>
{% endfor %}
{% else %}
<tr>
<td colspan="3">no records found</td>
</tr>
{% endif %}
</tbody>
</table>
foodIndex.html (Modal - Note {% csrf_token %}
)
<div id="modal-delete" class="modal fade" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Delete food item</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<form>
{% csrf_token %}
<button id='food-delete' class="btn btn-danger" type="submit">Delete</button>
</form>
</div>
</div>
</div>
</div>
foodIndex.html (script)
<script>
const deleteModal = document.getElementById('modal-delete');
deleteModal.addEventListener('show.bs.modal', event => {
const button = event.relatedTarget;
const foodName = button.getAttribute('data-bs-foodname');
const url = button.getAttribute('data-bs-url');
const modalBodyInput = deleteModal.querySelector('.modal-body ');
modalBodyInput.textContent = `Confirm deletion of ${foodName}`;
const deleteForm= deleteModal.querySelector('form');
deleteForm.setAttribute('action', url);
deleteForm.setAttribute('method', 'post');
});
</script>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论