在我的应用中,我有一个名为products的页面。在这个页面中,我在表格中显示了我的数据库中的记录。
表格的每一行都有两个按钮,用于添加和编辑特定行中的记录。
添加和编辑将通过我的名为Product的模型创建的表单来实现。 此表单将以模式显示,该模式将在单击添加或编辑按钮时显示。
我已经实现了添加和编辑功能,在单独的页面上显示表单,而不是模态。
下面是我的模特:
# models.py
from django.db import models
class Manufacturer(models.Model):
name = models.CharField(max_length=264)
def __str__(self):
return self.name
class Meta:
ordering = ["name"]
class Product(models.Model):
title = models.CharField(max_length=264)
description = models.CharField(max_length=1000, blank=True, null=True)
year_manufactured = models.PositiveIntegerField(blank=True, null=True)
manufacturer = models.ForeignKey(Manufacturer, on_delete=models.CASCADE)
def __str__(self):
return self.title
class Meta:
ordering = ["title"]
这是我的urls.py:
from django.conf.urls import url
from . import views
app_name = "products"
urlpatterns = [url(r'^products', views.ProductsView.as_view(), name="products"),
url(r"^product/new", views.add_new_product_view, name="add_new_product"),
url(r"^product/(?P<id>[0-9]+)/edit/", views.edit_product_view, name="edit_product")]
以下是我的观点:
from django.views.generic import DetailView, ListView, TemplateView
from django.http import JsonResponse
from django.shortcuts import render, get_object_or_404
from . import models
from products.forms import AddNewProductForm, EditProductForm
def index(request):
return render(request, 'products/products.html')
class ProductsView(ListView):
context_object_name = "products"
model = models.Product
template_name = "products/products.html"
form = AddNewProductForm()
def get_context_data(self, **kwargs):
context = super(ProductsView, self).get_context_data(**kwargs)
context["products"] = models.Product.objects.all().order_by("title")
context["form"] = self.form
return context
def add_new_product_view(request):
if request.method == "POST":
form = AddNewProductForm(request.POST)
if form.is_valid():
form.save(commit=True)
return JsonResponse({'msg': 'Data saved'})
else:
print("ERROR FORM INVALID")
return JsonResponse({'msg': 'ERROR FORM INVALID'})
else:
form = AddNewProductForm()
return JsonResponse({'form': form})
def edit_product_view(request, id):
instance = get_object_or_404(models.Product, id=id)
form = EditProductForm(instance=instance)
if request.method == "POST":
form = EditProductForm(request.POST, instance=instance)
if form.is_valid():
form.save(commit=True)
return JsonResponse({'form': form})
else:
print("ERROR FORM INVALID")
return JsonResponse({'form': form})
我在products.html上有这个:
{% extends "products/base.html" %}
{% load static %}
{% block title %}My Products{% endblock %}
{% block content %}
<div class="container" id="my-products-table-container">
<h2 class="text-left caption">Add, view and edit products</h2>
<hr>
<table class="table table-striped table-sm table-bordered" id="my-products-table">
<thead class="thead-inverse">
<tr class="head-row">
<th>Title</th>
<th>Description</th>
<th>Year</th>
<th>Manufacturer</th>
</thead>
<tbody>
{% for product in products %}
<tr class="table-row">
<td>{{ product.title }}</td>
<td>{{ product.description }}</td>
<td>{{ product.year_manufactured }}</td>
<td>{{ product.manufacturer }}</td>
<td><button type="button" class="btn btn-primary" data-toggle="modal" data-target="#addNewProductModalForm">Add New product</button></td>
<td><button onclick="findMyForm({{ product.pk }})">Update product</button></td>
{% endfor %}
</tbody>
</table>
</div>
<!-- Modal Add New Product-->
<div class="modal fade" id="addNewProductModalForm" tabindex="-1" role="dialog" aria-labelledby="addNewProductModalFormLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<form class="form" id="add_new_product_form">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="addNewProductModalFormLabel">Add New Product</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
{% csrf_token %}
{{ form.as_p }}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" onclick="addNewProduct()">Submit</button>
</div>
</div>
</form>
</div>
</div>
<!-- Modal Edit-->
<div class="modal fade" id="editProductModalForm" tabindex="-1" role="dialog" aria-labelledby="editProductModalFormLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<form class="form" id="edit_product_form" >
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="editProductModalFormLabel">Edit Product</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
{% csrf_token %}
<div id='showForm'></div>
</div>
<div class="modal-footer">
<input type="submit" class="btn btn-primary" value="Submit!">
</div>
</div>
</form>
</div>
</div>
<!-- JS Scripts -->
<script src="{% static "products/js/addProduct.js" %}"></script>
<script>
function findMyForm(productKey) {
$('#editProductModalForm').modal('show');
$.ajax({
type: 'GET',
url: '/product/' + productKey + '/edit/',
success: function(res) {
$("#showForm").html(res);
}
})}
</script>
{% endblock %}
我的JS脚本:
#addProduct.js
function addNewProduct(e) {
var addNewProductForm = $("#add_new_product_form");
$.ajax({
type: 'POST',
url: '/product/new/',
data: addNewProductForm.serialize(),
success: function(res){
alert(res['msg'])
}
})
}
我已更新了我的代码,以说明我可以在我的数据库中成功添加新产品。此外,我一直在努力从我的数据库编辑产品。
按下此按钮时:
<button onclick="findMyForm({{ product.pk }})">Update product</button>
应该包含编辑表单的模式,然后调用带有products.pk参数的函数findMyForm。之后,在产品编辑网址上执行ajax get请求。
根据我的urls.py,调用edit_product_view
。
这是我遇到EditProductForm不可序列化的错误。
另外,非常感谢Tico的不断帮助。
答案 0 :(得分:3)
有点难以理解你想要的东西。我假设您希望用户查看产品目录,然后当他单击特定产品的更新按钮时,您需要使用包含该产品正确加载数据的表单来触发模态。
所以我的答案基于这个假设
您的products_catalog.html中所需的第一个更改来自:
<a class="btn btn-outline-warning" href="{% url "simple_app:edit_product" product.pk %}"><i class="fa fa-pencil-square-o fa-1x" aria-hidden="true"></i></a>
触发功能的按钮:<button onclick="findMyForm()">Update product</button>
然后,您应该将该模式片段添加到products_catalog.html的末尾,但启动按钮除外。你不需要那个。还要在模态体<div id='showForm'></div>
内添加一个空div。
现在findMyForm函数应该做三件事。使用模式,从服务器中取出正确的表格并将表格放在模态主体上。
findMyForm(){
//the name myModal should be ID, as jquery notation suggests.
$('#myModal').modal('show');
$.ajax({
type: 'GET',
url: '/product/'+{{product.pk}}+'/edit/',
success: function(res){
$(#showForm).html(res)
}
})
GET在这里非常重要,因此呼叫会进入视图的右侧if
。因此,根据您的网址设置,这应该调用您的edit_product_view
,它应该返回您想要的表单。表单由ajax上的成功回调拾取并放入模态体中的空div。
但仍有一个大问题。您的视图是从头开始再次渲染模板,而您并不想要这样。所以诀窍是使用JsonResponse而不是渲染来避免重新加载(好吧,它无论如何都不能用于渲染)。所以这部分在你看来:
return render(request, 'simple_app/edit_product.html', {'form': form})
应该变成(记得导入from django.http import JsonResponse
):
return JsonResponse({'form': form})
请注意,您不再需要edit_product.html。上述过程在product_catalog.html页面中动态地在模态内部构建其内容。
确定。现在,您应该能够在产品目录中按下一个按钮,该按钮将弹出一个带有表单的模态到产品而不重新加载。我们假设您进行了更改并希望保存(POST部分视图)。模式类似:
save_form
。 {{form.as_p}}
呈现的内容)并对传递表单数据的'/product/'+{{product.pk}}+'/edit/'
进行ajax POST调用。编辑:
在模式中添加新产品:
{{form.as_p}}
。在模态页脚中,您应该将<input>
更改为<button>
标记,并将该按钮链接到js函数addNew()
。这样做会阻止默认表单提交。addNew是这样的:
addNew(){
var data = {
title: $('#title').val() //Not sure if title is the correct selector.
description: $('#description').val() // get correct id with browser tools.
...
}
// Ajax calls view. Stringify format your js object to a json string.
$.ajax({
type: 'POST',
url: '/product/new/',
data:JSON.stringify(data),
success: function(res){
alert(res['msg'])
}
})
}
数据格式化是棘手的部分。我不确定django表格是如何预期数据来的。您可能必须在视图中打印它并在传递默认验证功能之前进行操作。让我知道这是怎么回事。
return index(request)
即可返回JsonResponse({'msg':'Data saved'})
,以确保您了解其有效。所以你的ADD NEW按钮是默认的模态按钮。你按下它,你会得到一个模态打开,其中包含一个来自类视图的预渲染空表单。然后你有一个确定的按钮绑定到一个功能。此函数从表单收集数据并通过Ajax发送到服务器,您可以在其中将数据保存到模型中。您还可以使用JsonResponse从视图(对于其他用例)发回一些内容,这些内容将通过成功回调来获取。
希望这有帮助!