python - Django postgres SplitArrayField 在提交表单时抛出错误
问题描述
我是 django 的新手,发现自己有点卡在一些东西上。
我正在尝试实现一个提供如下表格的页面:
Days of the month
------------->
| +--------+-+-+-+ +--+--+
| |Employee|1|2|3| |30|31|
|names +--------+-+-+-+ +--+--+----------+
| |Name1 |0|0|8|....| 8| 8|SAVEBUTTON|
\/ +--------+-+-+-+ +--+--+----------+
每个单元格作为输入字段。
也可以随意提出一个更好的实现,我是一个 django(一般来说)新手,并且在我使用它时正在学习。
这是我尝试从我的视图中保存数据时遇到的错误:
File "/usr/local/lib/python3.8/site-packages/django/forms/forms.py", line 443, in changed_data
initial_value = field.to_python(hidden_widget.value_from_datadict(
File "/usr/local/lib/python3.8/site-packages/django/contrib/postgres/forms/array.py", line 195, in to_python
return [self.base_field.to_python(item) for item in value]
File "/usr/local/lib/python3.8/site-packages/django/contrib/postgres/forms/array.py", line 195, in <listcomp>
return [self.base_field.to_python(item) for item in value]
TypeError: to_python() missing 1 required positional argument: 'value'
django 管理页面上的一个不同但类似的错误:
File "/usr/local/lib/python3.8/site-packages/django/forms/forms.py", line 177, in is_valid
return self.is_bound and not self.errors
File "/usr/local/lib/python3.8/site-packages/django/forms/forms.py", line 172, in errors
self.full_clean()
File "/usr/local/lib/python3.8/site-packages/django/forms/forms.py", line 374, in full_clean
self._clean_fields()
File "/usr/local/lib/python3.8/site-packages/django/forms/forms.py", line 392, in _clean_fields
value = field.clean(value)
File "/usr/local/lib/python3.8/site-packages/django/contrib/postgres/forms/array.py", line 206, in clean
cleaned_data.append(self.base_field.clean(item))
TypeError: clean() missing 1 required positional argument: 'value'
相关models.py部分:
class DayField(forms.IntegerField):
widget=forms.NumberInput(attrs={'max': 24, 'min':0, 'size':2, 'maxlength':2,
'style':'width: 40px; -webkit-appearance: none; -moz-appearance: textfield;',
'oninput':"this.value=this.value.replace(/[^0-9]/g,''); if (this.value.length > this.maxLength) this.value = this.value.slice(0, this.maxLength);",
'class':'mr-2 form-control'
})
def to_python(self, value):
### copied from django/forms/fields.py
"""
Validate that int() can be called on the input. Return the result
of int() or None for empty values.
"""
value = super().to_python(value)
if value in self.empty_values:
return None
if self.localize:
value = formats.sanitize_separators(value)
# Strip trailing decimal and zeros.
try:
value = int(self.re_decimal.sub('', str(value)))
except (ValueError, TypeError):
raise ValidationError(self.error_messages['invalid'], code='invalid')
return value
def clean(self, value):
value = self.to_python(value)
self.validate(value)
self.run_validators(value)
return value
class MyArrayField(ArrayField):
# https://gist.github.com/danni/f55c4ce19598b2b345ef
def formfield(self, **kwargs):
defaults = {
'form_class': pforms.SplitArrayField,
'base_field': DayField,
'size': 31,
'remove_trailing_nulls': True,
}
defaults.update(kwargs)
return super(ArrayField, self).formfield(**defaults)
def to_python(self, value):
res = super().to_python(value)
if isinstance(res, list):
value = [self.base_field.to_python(val) for val in res]
return value
class Attendance(models.Model):
employee = models.ForeignKey(Employee, on_delete=models.CASCADE,verbose_name=_("employee"))
ref_date = models.DateField(verbose_name=_("date"))
attendance = MyArrayField(models.SmallIntegerField(), default=zeroes, size=31, verbose_name=_('attendance'))
def __str__(self):
return '%s' %(date_filter(self.ref_date, 'F Y'))
class Meta:
verbose_name = "Presenze"
verbose_name_plural = "Presenze"
视图.py:
from django.shortcuts import render, get_object_or_404
from .models import *
from datetime import date
from django.forms import modelformset_factory
from .forms import *
def month_attendees(request, company_id, year, month):
message = ''
company = get_object_or_404(Company, pk=company_id)
months = Attendance.objects.filter(ref_date__gte=date(year, month, 1),
ref_date__lt=date(year, month+1, 1),
employee__company=company,
)
AttendanceFormSet = modelformset_factory(Attendance, fields=('attendance',), max_num=len(months))
if request.method == 'POST':
formset = AttendanceFormSet(data=request.POST)
if formset.is_valid():
print(formset.changed_objects)
formset.save()
message = "Saved"
else:
formset= AttendanceFormSet(queryset=months)
context = {'months':months, 'message':message, 'formset':formset}
return render(request, 'formazione/month_attendees.html', context)
month_attendees.html
<form method="post" class="form-inline">
{% csrf_token %}
{{ formset }}
<input type="submit" value="Save" class="btn btn-primary">
</form>
解决方案
推荐阅读
- android - 如何在使用导航时关闭 Android 中的当前片段?
- sql-server - 如何将关联表 ID 与 AND 条件匹配
- c# - 使用 SignalR 检测死连接
- java - 这个 leetcode 问题的记忆。我如何记住这个递归解决方案
- node.js - 平均堆栈应用程序在 AWS EC2 实例上无法正常运行
- pandas - json_normalize:访问库和数组形式的数据
- typo3-6.2.x - Typo3 6.2 升级版本矩阵问题
- javascript - 有没有办法提取 csv 文件并将其转换为矢量图/值?
- android - 带有喷气背包导航的底部导航视图?
- netlogo - 最后,如何在文件中打印所有剩余海龟的 xcor 和 ycor?