我正在制作一个库存应用程序,我可以在其中更新我的'home.html'的产品值。
我的proj名称是库存应用名称是myapp
我面临的问题是,每次我从主页上更新股票的价值时,都会添加一个新产品,而不是更新我想要的产品!我正在使用Django提供的ModelsForm类。使用django = 1.11和python = 3.6
我的项目的urls.py:
from django.conf.urls import url,include
from django.contrib import admin
from myapp.views import home
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^myapp/', include('myapp.urls', namespace="myapp")),
url(r'^myapp/home/', home, name='home'),
]
我的forms.py:
from django import forms
from .models import Inventory
class Operations(forms.ModelForm):
class Meta:
model = Inventory
fields = ('stocks_left',)
我的应用程序的型号:
from django.db import models
import uuid
class Inventory(models.Model):
"""
Model representing a the inventory.
"""
id = models.UUIDField(primary_key=True, default=uuid.uuid4)
inventory_name = models.CharField("INVENTORY NAME" ,max_length=200, help_text="This contains the Inventory name:")
short_name = models.CharField(max_length=20, help_text="This contains an abbreviation:")
inventory_code = models.IntegerField("INVENTORY CODE" ,default = '0', help_text="This contains the Inventory code:")
price = models.IntegerField(default = '0')
stocks_left = models.IntegerField("STOCKS LEFT",default = '0')
def __str__(self):
"""
String for representing the Model object (in Admin site etc.)
"""
return '{0} ({1}) ({2})'.format(self.inventory_name,self.inventory_code,self.stocks_left)
我的应用程序的urls.py
from django.conf.urls import url
from . import views
from django.contrib.auth.views import login
app_name= 'myapp'
urlpatterns = [
url(r'^$', login, {'template_name': 'myapp/login.html'}),
]
和我的Views.py
from django.shortcuts import render,redirect
from django.contrib import auth
from django.contrib.auth.models import User
from django.views import generic
from django.http import HttpResponse
from myapp.models import Inventory
from .forms import Operations
def home(request):
names = Inventory.objects.all()
if request.method == "POST":
form = Operations(request.POST)
if form.is_valid():
stocks_left = form.save(commit=False)
stocks_left.save()
return redirect('myapp/home.html')
else:
form = Operations()
return render(request, 'myapp/home.html', { "names": names, "form": form})
和我的家.html模板:
<html>
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<title>Inventory</title>
</head>
<body>
<h1>Welcome!</h1>
<div class="container">
<table border="5" cellpadding="10" width="1000">
<thead align="center">
<tr>
<th align="center">#</th>
<th align="center">Name</th>
<th align="center">Inventory Code</th>
<th align="center">Stocks left</th>
<th align="center">Operations</th>
</tr>
<tr>
{% for x in names %}
<td align="center"> {{ x }}</td>
<td align="center"> {{ x.inventory_name }}</td>
<td align="center"> {{ x.inventory_code }}</td>
<td align="center"> {{ x.stocks_left }}</td>
<td><form method="POST">{% csrf_token %}{{form}}<button type="button" class="btn btn-primary"><span class="glyphicon glyphicon-plus"></span></button></form><br></td>
</tr>
{% endfor %}
</table>
</div>
</body>
这是您可以做的,
以表单创建2个字段
class Operations(forms.ModelForm):
class Meta:
model = Inventory
fields = ('stocks_left','inventory_name')
当您在视图中获取数据时,
if request.method == "POST":
form = Operations(request.POST)
if form.is_valid():
inv_obj = form.cleaned_data.get('inventory_name')
inv_model_obj = Inventory.objects.get(inventory_name=inv_obj) #make sure to declare in the models that this inventory_name is unique
inv_model_obj.stocks_left = form.cleaned_data.get('stocks_left')
inv_model_obj.save()
return redirect('myapp/home.html')
如果您不将instance=the_instance_you_want_to_edit
传递给Modelform,它将创建一个新实例。Modelform还将如何知道您要编辑哪种模型实例?
basemodelform。 init
if instance is None:
# if we didn't get an instance, instantiate a new one
self.instance = opts.model()
object_data = {}
else:
self.instance = instance
object_data = model_to_dict(instance, opts.fields, opts.exclude)
无论如何,如果您想将其全部保留在一页上,那真的不会很好。您要么手动输入object_ID以稍后传递到Modelform。或者,您创建一个表单集,每个表单代表一个库存对象以及" stocks_left"的输入字段。
前者有点iffy,因为如果您将主键错误误认为,则会在不注意的情况下更改错误的库存库存(或在道路上丢下ntotexist错误(。如果您只想更改单个库存,则后者是总的杀伤力。
您有两个选项,任何一个选项都需要另一个页面/模板。一个页面显示您的概述,另一页用于更新库存的库存。概述包含指向单个更新页面的链接。
捕获要从URL编辑的对象的主要键。
url(r'^myapp/home/([0-9]+)/$)', home, name='home-update')
URL调度程序将使用请求和捕获的参数调用您的home
视图功能,您可以使用它实例化Modelform。
def home(request, pk):
names = Inventory.objects.all()
if request.method == "POST":
form = Operations(request.POST, instance=Inventory.objects.get(pk=pk)
if form.is_valid():
form.save()
return redirect('myapp/home.html')
else:
form = Operations()
return render(request, 'myapp/a_very_basic_template_to_display_a_form.html', {"form": form})
或使用基于类的UpdateView(用于您的"更新"页面(:
class InventoryStockUpdateView(views.generic.UpdateView):
model = Inventory
template_name = 'myapp/a_very_basic_template_to_display_a_form.html'
fields = ['stocks_left']
success_url = reverse_lazy('home')
在urls.py中使用此内容:
url(r'^myapp/home/(?P<pk>[0-9]+)/$)', InventoryStockUpdateView.as_view(), name='home-update')
要使用主键31415编辑库存,然后将'... home/31415'键入浏览器。
更新:您是否看过Django的管理员行动?他们让您通过通过复选框选择它们,然后对其进行管理操作来编辑实例。虽然这可能不是您想要的,但研究他们的工作方式应该如何教您一些技巧,这些技巧可以帮助您完成当前的任务。
也许给您一些有关如何进行操作的指示:将<a>
标签添加到模板中,两个(/-(对于您显示的每个实例的"行"。每个标签的HREF属性应包含该行的实例和元素的"作业"(添加或减去库存(。这两个值将在URL conf中使用,就像我上面描述的...
至于如何正确构建HREF属性;模板标签文档应该有所帮助。
也许是这样:
<tr>
{% for x in names %}
<td align="center"> {{ x }}</td>
<td align="center"> {{ x.inventory_name }}</td>
<td align="center"> {{ x.inventory_code }}</td>
<td align="center"> {{ x.stocks_left }}</td>
<td><a href={% url ??? %}>click me to subtract!</a></td>
<td><a href={% url ??? %}>click me to add!</a></td>
</tr>
{% endfor %}
当然,您还需要一个新的视图功能来处理这些URL,但是这些URL应该很难弄清楚。