是的,这需要做很多工作,所以就到这里吧。
当我想创建一个使用 tabledata 而不是用户输入数据的表单时,我使用以下类:
class TableRowForm():
'''
This form is special, because usually, forms include a range of inputs
to be filled out by the user. This form however, no inputs are filled in. The
form is given a queryset of objects and a list of field names, and with those,
a table is made. Each row in the table represents an object. clicking a row
will select the object. Multiple submit buttons can be given with various
functions. What these buttons have in common is that they all operate on the
selected objects, e.g. selecting three objects and pressing delete will delete
those three objects. The form is different in that it does not create new objects,
it manipulates already existing objects.
'''
def __init__(self, queryset, fields):
if not fields:
raise Exception('A TableRowForm must be supplied both queryset and fields')
self.queryset = queryset
self.fields = fields
def __unicode__(self):
'''
Builds the html table rows for the form.
'''
if not self.queryset: return '<tr><td>No data...<td></tr>'
colcount = 0
res = ""
res += "<tr>"
for f in self.fields:
res += "<th>"+self.queryset[0]._meta.get_field_by_name(f)[0].verbose_name+"</th>"
res += "</tr>\n"
for obj in self.queryset:
res += '<tr onclick="selectRow(this)">'
res += '<td><input style="display:none;" type="checkbox" name="slct" id="%s" value="%s"/>'%(obj.pk,obj.pk)
vals = [getattr(obj, x) for x in self.fields]
colcount = len(vals)
for x in vals:
res += '%s</td><td>'%(str(x))
res = res[:-4]
res += '</tr>\n'
res += '<tr><th colspan="%d"><span style="font-size:9pt;"><b>Selctable table:</b> Click a row to select it</span></th></tr>'%(colcount)
# Add the javascript that implements functionality
res += '''\
<script>
// Allows for selectable tablerows in forms
function selectRow(row)
{
// Check/uncheck the checkbox
var chk = row.getElementsByTagName('input')[0];
chk.checked = !chk.checked;
// Color the row in response to the checkbox's boolean value
if (chk.checked) {
row.style.backgroundColor = 'gray';
} else {
row.style.backgroundColor = 'white';
}
}
</script>'''
return res
这样做是它需要一个数据查询集和一个要显示的所需字段的列表,然后它使用提供的数据构建表格,并为每一行隐藏一个复选框。
建立表格后,将附加一个 javascript 以帮助选择复选框并相应地为表格行着色。
创建这样的表单可能是这样的:
trform = TableRowForm(queryset=Item.objects.all(),
fields=('serial',
'prod',
'discount',
'price',
'account',
'vat',))
在模板中使用此表单时,应该这样做
<form action="{% url bla.bla.bla %}" method="post">
<table>
{{ form|safe }}
</table>
<input type="submit" name="testform" value="Test" />
</form>
过滤器“|safe”确保 HTML 被解释而不是仅仅写为文本。
表格标签没有自动生成的原因是表格可能不是整个表格本身,所以表格只为表格生成行。
如果我们有多个提交按钮,则将“名称”属性放在表单中的提交按钮上是一种管理要执行的操作的好方法。可以想象对一张数据表执行任意数量的操作。
最后,处理表单数据,当点击提交按钮时,可以如下完成:
if 'testform' in request.POST:
# These two lines fetch all the selected objects from the tablerow form
selections = request.POST.getlist('slct')
its = Item.objects.filter(pk__in=selections)
此示例假定 table-row-form 上使用的对象类型是 Item。'slct' 是自动赋予表单中复选框的名称。可以想象,通过允许从 request.POST 的实例创建表单,让表单自动从 POST 数据中提取信息,从而使这变得更智能,但我还没有做到这一点;)
“request.POST.getlist('slct')” 基本上获取所有以 'slct' 命名的值并将它们放在一个列表中。在此之后,您可以通过查询主键轻松检索它们所代表的对象。
我希望这对我以外的人有用。我为我所取得的成就感到非常自豪:)