首页 > 解决方案 > 基于 Django 类的表单仅更新最终的帖子值

问题描述

正如标题所述,我有一个我正在尝试更新的表,它只更新帖子中的最终值,据我所知,如果我想更新多条记录,我必须遍历我的请求对象并更新表单实例我的数据库中指定的 ID。

在提交之前,所有记录的 aprice_checked为 0。

在此处输入图像描述

然后之后 - 您可以从发布请求中看到最终值更新了所有记录!

在此处输入图像描述

postgres table

在此处输入图像描述

有问题的代码更新了我的模型表单实例。

def post(self,request):
    if request.method=='POST':
    
        for key in request.POST.getlist('product_id'):
                product_update = ProductTable.objects.get(id=key)
                form = ProductUpdateForm(request.POST,instance=product_update)
                print(form)
                if form.is_valid():
                    form.save()
                messages.success(request,message='price checked...') 
        return redirect('product')

有人可以帮忙吗?我已经在这一点上超过 2 周了。


模型/表格/视图供参考。

models.py

from django.db import models

class ProductTable(models.Model):

    id = models.AutoField(
        primary_key=True,
        editable=False
    )

    product_name = models.TextField(max_length=255,null=False)
    price = models.DecimalField(max_digits=6,decimal_places=2,null=False)
    from_date = models.DateTimeField()
    to_date = models.DateTimeField(null=True)
    price_checked = models.IntegerField(default=0,null=False)

    def __str__(self : str) -> str:
        return f"{self.product_name} - {self.id} with a price check of {self.price_checked}"

forms.py

from django.forms import ModelForm
from .models import ProductTable


class ProductUpdateForm(ModelForm):
    class Meta:
        model = ProductTable
        fields = ('price_checked',)

views.py

from typing import Any, Dict

from django.contrib import messages
from django.contrib.auth.mixins import LoginRequiredMixin
from django.shortcuts import redirect
from django.views.generic import ListView
from django.db import transaction
from .forms import ProductUpdateForm
from .models import ProductTable


class TableDataView(LoginRequiredMixin,ListView):
    model = ProductTable
    context_object_name = 'product'
    template_name = 'tables/product.html'


    def get_context_data(self, **kwargs: Any) -> Dict[str, Any]:
        context = super().get_context_data(**kwargs)

        context['product'] = ProductTable.objects.filter(pk__in= [4607,4642, 4645])

        return context


    def post(self,request):
        if request.method=='POST':
        
            for key in request.POST.getlist('product_id'):
                    product_update = ProductTable.objects.get(id=key)
                    form = ProductUpdateForm(request.POST,instance=product_update)
                    print(form)
                    if form.is_valid():
                        form.save()
                    messages.success(request,message='price checked...') 
            return redirect('product')

product.html

{% extends '_base.html' %} {% block content %} {% load crispy_forms_tags %} 
<form method="POST" action="">
    {% csrf_token %} 
    {{ form|crispy }}
  <div class="container mx-flex pt-5 mb-5">
    <table class="table" id="table">
      <thead>
        <tr>
          <th>Product</th>
          <th>Price</th>
          <th>Date</th>
          <th>Input</th>
        </tr>
      </thead>
      <tbody>
        {% for data in product %}
        <tr>
          <th>{{ data.product_name }}</th>
          <th>{{ data.price }}</th>
          <th>{{ data.from_date }}</th>
          <th>
            <input type="hidden" name="product_id" value="{{data.id}}" />
            <input class="form" name="price_checked" id="priced_checked" type="number" placeholder="{{ data.price_checked }}"/>
            <input type="submit" value="OK">
          </th>
        </tr>
        {% endfor %}
      </tbody>
    </table>
  </div>
</form>
{% endblock content %}

request.POST

 <QueryDict: {'csrfmiddlewaretoken': ['p0j3e0UbrY1VuFEAnJWopaCICCxOPj8v2OkLRZZiGlUa4YtxGwduD2bAIrm91VKe'], 'product_id': ['4607', '4642', '4645'], 'price_checked': ['1', '2', '3']}>

标签: pythondjango

解决方案


阅读表单集文档后,我认为它应该是这样的。
视图python将一个表单集返回给模板,并在post函数中创建表单集request.POST

def get_context_data(self, **kwargs: Any) -> Dict[str, Any]:
    context = super().get_context_data(**kwargs)

    ProductFormSet = modelformset_factory(ProductTable)
    context['product_formset'] = ProductFormSet(queryset=ProductTable.objects.filter(pk__in= [4607,4642, 4645]))

    return context


def post(self,request):
    if request.method=='POST':
        ProductFormSet = modelformset_factory(ProductTable)
        formset = ProductFormSet(request.POST)
        if formset.is_valid():
            formset.save()
            messages.success(request,message='price checked...') 
        return redirect('product')

在模板中我已经标记了更改,重要的是{{ product_formset.management_form }}在开始表单{{ form.id }}中。每个循环,每个单元格数据应该是{{ form.product_name.value() }}{{ form.product_name.data }},你可以试试

{% extends '_base.html' %} {% block content %} {% load crispy_forms_tags %} 
<form method="POST" action="">
    {% csrf_token %} 
    {{ form|crispy }}
    <!-- changed -->
    {{ product_formset.management_form }}
  <div class="container mx-flex pt-5 mb-5">
    <table class="table" id="table">
      <thead>
        <tr>
          <th>Product</th>
          <th>Price</th>
          <th>Date</th>
          <th>Input</th>
        </tr>
      </thead>
      <tbody>
        <!-- changed -->
        {% for form in product_formset %}
        {{ form.id }}
        <tr>
          <td>{{ form.product_name.value() }}</td>
          <td>{{ form.price.value() }}</td>
          <td>{{ form.from_date.value() }}</td>
          <td>
            {{ form.price_checked }}
            
          </td>
        </tr>
        {% endfor %}
      </tbody>
    </table>
  </div>
  <input type="submit" value="submit">
</form>
{% endblock content %}

也许这对你没有帮助,因为我从来没有使用过 django 形式的东西。
我猜你是一个想要遵循每个 django 原则的精确人。
但据我所知,传统形式有很多限制,一些 ajax 或 reactjs 更灵活。


推荐阅读