gpt4 book ai didi

django - 如何从模态内的模型创建和提交表单?

转载 作者:行者123 更新时间:2023-12-05 03:07:58 25 4
gpt4 key购买 nike

在我的应用程序中,我有一个名为产品的页面。在此页面中,我在表格中显示来 self 的数据库的记录。

表格的每一行都有两个按钮,用于添加和编辑特定行中的记录。

添加和编辑将通过我的模型创建的名为 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">&times;</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">&times;</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 函数。之后,对产品编辑 url 执行 ajax get 请求。

根据我的 urls.py,调用了 edit_product_view。在这里我遇到了 EditProductForm 不可序列化的错误。

另外,非常感谢 Tico,感谢他一直以来的帮助。

最佳答案

从一开始就很难理解你想要什么。我假设您希望用户看到产品目录,然后,当他单击特定产品的更新按钮时,您需要使用包含该产品正确加载数据的表单来触发模式。
所以我的回答基于这个假设

您的 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 <div id='showForm'></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 中。

但是还有一个大问题。您的 View 正在从头开始再次呈现模板,而您不希望这样。所以诀窍是使用 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 页面的模态内动态构建其内容。

好的。现在您应该能够在产品目录中按下一个按钮,该按钮将弹出一个带有与产品相关的表单的模式,而无需重新加载。假设您进行了更改并想要保存( View 的 POST 部分)。模式类似:

  • 你需要在你的模式中有一个按钮来触发一个函数 save_form .
  • 函数将使用 jquery 从表单中获取新值(使用浏览器工具找出 {{form.as_p}} 呈现的内容)并对 '/product/'+{{product.pk}}+'/edit/' 进行 ajax POST 调用传递表单数据。
  • 在您的 View 中保存数据并呈现 index.html(或返回 JsonResponse({'res':'您的数据已保存'})并使用 ajax 成功回调将其打印在您的 html 中的某处)。

编辑:

在模式中添加新产品:

  • 更改您的 ProductView 以将空表单传递给 products.html 模板。
  • Minimal products.html 是一个模式(带有默认按钮)。在模态主体中,您应该呈现一个空表单 {{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 表单如何期望数据到来。在通过默认验证函数之前,您可能必须在 View 中打印并进行操作。让我知道这对你有何影响。

  • 您上次观看没问题。只需更改 return index(request)返回 JsonResponse({'msg':'Data saved'})以确保您理解它有效。

因此您的添加新按钮是默认模式按钮。你按下它,你会打开一个模态,其中包含一个来自你的类 View 的预呈现的空表单。然后你有一个 ok BUTTON 绑定(bind)到一个函数。此函数从您的表单收集数据并通过 Ajax 发送到服务器,您将数据保存到您的模型中。您还可以使用 JsonResponse 从 View (对于其他用例)发回一些内容,这将由成功回调获取。

希望这对您有所帮助!

关于django - 如何从模态内的模型创建和提交表单?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46311729/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com