【发布时间】:2016-11-24 23:22:25
【问题描述】:
我有一个 Django 项目,用于管理多个项目以及与项目相关的所有信息。
在其中一个名为“概念”的网页上,有一个表单,它在一个文本框中输入不含增值税的成本值,在另一个文本框中显示含增值税的成本,并有一个datepicker 字段允许用户选择支付押金的日期(如果有的话)。
我在获取表单以保存用户输入的当前日期值时遇到了一些麻烦 - 如果用户填写表单中的三个字段(成本 exc 增值税 - 由用户输入,成本inc vat- 根据 const exc vat, & date) 自动生成,然后刷新页面,两个成本字段保留其值,但 'date' 字段恢复为空白。
当我检查“日期”字段的页面元素时,我可以看到它位于以下 HTML 结构中:
<body>
...
<div class="wrapper">
<div class="content">
<form method="POST" .... data-view-url=".../concept_save_ajax/">
<div class="col-12-box">
<div>
<table class="right fixed m-t-md">
<tbody>
<tr>
...
<td class="p-r-md">Deposit exc VAT</td>
<td class="p-r-md">
<input class="currency" id="id_amount_exc_vat" name="amount_exc_vat" type="number" value="280">
<td class="p-r-md>
<input class="datepicker hasDatepicker" data-original-value id="id_date_received" name="date_received" type="text"> == $0
</td>
</tr>
</tbody>
</table>
</div>
</div>
</form>
</div>
</div>
</body>
编辑
虽然这是我在浏览器中检查时页面的 HTML 结构,但我的项目中 HTML 文件的实际代码是:
{% block content %}
<form method="POST" enctype="multipart/form-data" data-vat-status="{{project.vat_status}}" data-view-url="{% url 'projects:concept_save_ajax_2' project.id %}" class="autosave_form formset full-width" action="{% url 'projects:upload_budget_pdfs' project.id %}">
...
</form>
<form method="POST" enctype="multipart/form-data" data-vat-status="{{project.vat_status}}" data-view-url="{% url 'projects:concept_save_ajax' project.id %}" class="autosave_form full-width">
{% csrf_token %}
<div class="col-12 box">
<div>
<table class="right fixed m-t-md">
<tr>
{% for hidden in deposit_form.hidden_fields %}
{{hidden}}
{% endfor %}
{% for field in deposit_form.visible_fields %}
<td class="p-r-md">{{field.label}}</td><td class="p-r-md">{{field}}</td>
{% endfor %}
<td><a class="email_trigger button" data-view-url="{% url 'comms:open_email_template' project.id %}?template=7">Raise invoice</a></td>
</tr>
</table>
</div>
</div>
<div class="col-6 box">
...
</div>
<div class="col-6 box">
...
</div>
</form>
{% endblock content %}
结束编辑
鉴于表单方法指定为POST,我希望使用concept_save_ajax 视图保存输入表单的信息,如开头<form> 标记内所示。
此视图在views.py 中定义:
def concept_save_ajax(request, project_id):
""" Save concept forms """
if not request.is_ajax():
raise Http404('Ajax only')
if request.method == 'POST':
project = Project.objects.prefetch_related('budget_versions', 'budget_overview').get(pk=project_id)
form_instances = [
# [DepositForm, project.deposit],
[DepositInfoForm, project.deposit],
[BudgetNotesForm, project.budget_overview],
[EndDetailsForm, project.end],
]
# Save the forms
for form_instance in form_instances:
form = form_instance[0](request.POST, instance=form_instance[0]) #1]) should be '0' for first element?
if form.is_valid() and form.has_changed():
print form_instance[0], "is valid.", form_instance[0]
updated_details = form.save()
elif form.has_changed():
print form_instance[0], "is not valid", form.errors
return JsonResponse({'error': form.errors})
# url = '/projects/{0}/?tab={1}'.format(project_id, tabs[3])
return JsonResponse({'success': 'Saved'})
else:
raise Http404('Request is not a post')
我可以看到,如果满足条件 form.is_valid() 和 form.has_changed() 时,此视图正在调用 form.save(),但由于某种原因,当我为 ' 输入新值时,这似乎并没有实际保存日期”字段。
我已尝试在控制台中对此进行测试 - 但应保存“日期”值的字段似乎为空...在控制台中,我运行了:
from projects import models
from projects.models import Project
allPrjcts = Project.objects.all()
br = allPrjcts.filter(project_name="1 Brocks Road")
from costing import models
from costing.models import Deposit
allDpsts = Deposit.objects.all()
brocksRoad = br[0] # I know that this is the only project returned by the filter
brDpst = allDpsts.get(project_id = 6311L) # I know that this is the ID for the 'brocksRoad' project
然后,当我在控制台中运行brDpst.date_received时,什么都没有显示,表明我在网页上的“日期”字段中输入的值似乎没有被保存...
有什么想法吗?如何获取“日期”字段的值以自动保存,以便在我重新加载页面时显示,与该表单上的“成本”字段相同?
如果我在控制台中运行brDpst.amount_exc_vat,它会显示值:
十进制('280.00')
这是我在文本框中输入的金额,所以很明显表单正在保存......只是由于某种原因,“日期”字段的值没有被保留......
编辑
DepositInfoForm 当前是这样定义的:
class DepositInfoForm(ValidatedForm):
...
date_received = MoonDateField(required=False, label="Date deposit received", widget=forms.DateInput(format='%d/%m/%Y', attrs=({'class':'datepicker'})))
我尝试将其更改为:
class DepositInfoForm(ValidatedForm):
...
date_received = MoonDateField(required=False, label="Date deposit received", widget=forms.DateInput(format='%d/%m/%Y', attrs=({'class':'datepicker', 'type':'date'})))
正如@neverwalkaloner 所建议的那样,但如果我这样做,当我选择表单上的date_received 字段时,下拉菜单中会显示两个日历...我想使用已经存在的日历可供选择日期,而不是我传递给date_received 变量的'type':'date' 参数添加的日期...
编辑
我已经为我的DepositInfoForm(...) 类添加了一些调试,似乎当对采用数值的表单字段进行更改时,它的save() 方法正在被调用,但save() 没有被调用当对包含日期的表单字段进行更改时...我不明白这是为什么...?
DepositInfoForm(...) 类定义为:
class DepositInfoForm(ValidatedForm):
amount_exc_vat = forms.IntegerField(required=False, widget=forms.NumberInput(attrs={'class': 'currency',}),label="Deposit exc VAT")
amount_inc_vat = forms.IntegerField(required=False, widget=forms.NumberInput(attrs={'class': 'currency', 'readonly':'readonly',}),label="Inc VAT")
date_received = MoonDateField(required=False, label="Date deposit received", widget=forms.DateInput(format='%d/%m/%Y', attrs=({'class':'datepicker'})))
class Meta:
model = Deposit
fields = ('amount_exc_vat', 'amount_inc_vat', 'date_received')#,'received')
def __init__(self, *args, **kwargs):
print "__init__ method being called in DepositInfoForm"
instance = kwargs.get('instance', {})
project = instance.project
try: amount_exc_vat = int(round(instance.amount_exc_vat))
except TypeError: amount_exc_vat = None
try: amount_inc_vat = int(round(project.deposit.amount_inc_vat))
except TypeError: amount_inc_vat = None
try: date_received = instance.date_received
except TypeError: date_received = None
initial = kwargs.get('initial', {})
initial={
'received': project.deposit_received,
'amount_exc_vat': amount_exc_vat,
'amount_inc_vat': amount_inc_vat,
'date_received': date_received,
}
kwargs['initial'] = initial
super(DepositInfoForm, self).__init__(*args, **kwargs)
self.fields['date_received'].widget.attrs.update({'data-original-value': self.initial['date_received'] or ''})
def save(self, commit=True):
print "Save method being called in DepositInfoForm"
deposit = self.instance
data = self.cleaned_data
print "save method being called in DepositInfoForm (projects/forms.py line 1142)"
if 'date_received' in self.changed_data:
if not data['date_received'] == '':
deposit.project.deposit_received = True;
self.deposit_r = True
deposit.project.upgrade_detailed_status(Project.ds75)
else:
deposit.project.deposit_received = False;
deposit.project.save()
if ('amount_exc_vat' in self.changed_data or 'date_received' in self.changed_data in self.changed_data) and data['amount_exc_vat'] and data['date_received']:
send_message(message_template=2, project=self.instance.project)
self.deposit_r = True
if hasattr(self, 'deposit_r'):
# Make the payment
deposit_payment = Payment(project=deposit.project, is_booking_deposit=True, amount_exc_vat=data['amount_exc_vat'], date_paid=data['date_received'])
return super(DepositInfoForm, self).save(commit=commit)
编辑
当我尝试更改网页上表单中的日期时,虽然最初显示的是新日期,但如果我刷新页面,它的值会变回我更改之前的值。当我更改表单中“日期”字段的值时,控制台显示以下输出:
Exception in thread Thread-42:
Traceback (most recent call last):
File ".../threading.py", line 810, in __bootstrap_inner
self.run()
File ".../models.py", line 138, in run
msg.send(self.fail_silently)
File ".../message.py", line 292, in send
return self.get_connection(fail_silently).send_messages([self])
File ".../smtp.py", line 100, in send_messages
new_conn_created = self.open()
File ".../smtp.py", line 67, in open
self.connection.login(self.username, self.password)
File ".../smtplib.py", line 615, in login
raise SMTPAuthenticationError(code, resp)
SMTPAuthenticationError: (535, '5.7.3 Authentication unsuccessful')
但我实际上并没有更改它在Traceback 中抱怨的任何文件...是什么导致了这个异常?
【问题讨论】:
-
您需要显示表单的代码,以及您提交的数据的格式。
-
我已经编辑了我的 OP 以显示表单的定义。