Yep, forms the base for what I needed. made a small patch to extend it a bit, the patch includes some doc updates as well.
This allows for: {{extend 'layout.html'}} Registration form {{lbl=form.custom.label}} {{wid=form.custom.widget}} {{=form.custom.form.start}} <table> <tbody> {{for f in form.fields:}} {{if step==1:}}<tr>{{pass}} <td>{{=f}}</td> <td>{{=lbl[f]}}</td> <td>{{=wid[f]}}</td> {{step=step+1}} {{if step==2:}}</tr>{{step=1}}{{pass}} {{pass}} </tr> </tbody> </table> {{=form.custom.submit}} {{=form.hidden_fields()}} {{=form.custom.form.close}} I've not yet managed to get {{=form.hidden_fields()}} in to {{=form.custom.form.close}} === modified file 'web2py/gluon/sqlhtml.py' --- web2py/gluon/sqlhtml.py 2009-05-31 18:42:23 +0000 +++ web2py/gluon/sqlhtml.py 2009-06-04 16:56:52 +0000 @@ -2,7 +2,7 @@ # -*- coding: utf-8 -*- """ -This file is part of web2py Web Framework (Copyrighted, 2007) +This file is part of web2py Web Framework (Copyrighted, 2007-2009) Developed by Massimo Di Pierro <mdipie...@cs.depaul.edu> License: GPL v2 """ @@ -289,13 +289,22 @@ nbsp = XML(' ') # Firefox2 does not display fields with blanks FORM.__init__(self, *[], **attributes) ofields = fields + + # if no fields are provided, build it from the provided table + # will only use writable or readable fields, unless forced to ignore if fields == None: fields = [f for f in table.fields if \ ignore_rw or table[f].writable or table[f].readable] self.fields = fields + + # make sure we have an id if not 'id' in self.fields: self.fields.insert(0, 'id') + self.table = table + + # try to retrieve the indicated record using its id + # otherwise ignore it if record and isinstance(record, (int, long, str, unicode)): records = table._db(table.id == record).select() if records: @@ -303,6 +312,7 @@ else: record = None self.record = record + self.record_id = None self.trows = {} xfields = [] @@ -311,43 +321,57 @@ self.custom.dspval = Storage() self.custom.inpval = Storage() self.custom.label = Storage() + self.custom.comment = Storage() + self.custom.widget = Storage() + self.custom.linkto = Storage() + for fieldname in self.fields: if fieldname.find('.') >= 0: continue field = self.table[fieldname] + if comments: comment = col3.get(fieldname, field.comment) or '' else: comment = '' + self.custom.comment[fieldname] = comment + if labels != None and fieldname in labels: label = labels[fieldname] else: label = str(field.label) + ': ' self.custom.label[fieldname] = label + field_id = '%s_%s' % (table._tablename, fieldname) label = LABEL(label, _for=field_id, _id='%s__label' % field_id) row_id = field_id + '__row' if fieldname == 'id': self.custom.dspval.id = nbsp self.custom.inpval.id = '' + widget = '' if record: if showid and 'id' in fields and field.readable: v = record['id'] + widget = SPAN(v, _id=field_id) self.custom.dspval.id = str(v) - xfields.append(TR(label, SPAN(v, _id=field_id), + xfields.append(TR(label, widget, comment, _id='id__row')) self.record_id = str(record['id']) + self.custom.widget.id = widget continue + if record: default = record[fieldname] else: default = field.default + cond = readonly or \ (not ignore_rw and not field.writable and field.readable) if default and not cond: default = field.formatter(default) dspval = default inpval = default + if cond: # ## if field.represent is available else @@ -391,11 +415,16 @@ continue else: inp = self.widgets.string.widget(field, default) + tr = self.trows[fieldname] = TR(label, inp, comment, _id=row_id) xfields.append(tr) self.custom.dspval[fieldname] = dspval or nbsp self.custom.inpval[fieldname] = inpval or '' + self.custom.widget[fieldname] = inp + + # if a record is provided and found, as is linkto + # build a link if record and linkto: for (rtable, rfield) in table._referenced_by: query = urllib.quote(str(table._db[rtable][rfield] @@ -405,28 +434,47 @@ continue if labels and lname in labels: lname = labels[lname] - xfields.append(TR('', A(lname, _class='reference', + widget = A(lname, _class='reference', _href='%s/%s?query=%s' % (linkto, - rtable, query)), col3.get(olname, '' + rtable, query)) + xfields.append(TR('', widget, col3.get(olname, '' ), _id='%s__row' % olname.replace('.' , '__'))) + self.custom.linkto[olname.replace('.', '__')] = widget + + # when deletable, add delete? checkbox + self.custom.deletable = '' if record and deletable: + widget = INPUT(_type='checkbox', _class='delete', + _id='delete_record', + _name='delete_this_record') xfields.append(TR(LABEL(delete_label, _for='delete_record', - _id='delete_record__label'), - INPUT(_type='checkbox', _class='delete', - _id='delete_record', - _name='delete_this_record'), + _id='delete_record__label'), widget, col3.get('delete_record', ''), _id='delete_record__row')) + self.custom.deletable = widget + # when writable, add submit button + self.custom.submit = '' if not readonly: - xfields.append(TR('', INPUT(_type='submit', - _value=submit_button), + widget = INPUT(_type='submit', + _value=submit_button) + xfields.append(TR('', widget, col3.get('submit_button', ''), _id='submit_record__row')) + self.custom.submit = widget + # if a record is provided and found + # make sure it's id is stored in the form if record: if not self['hidden']: self['hidden'] = {} self['hidden']['id'] = record['id'] + + form = Storage() + (form.start, form.close) = self._xml() + form.start = XML("<%s %s>" % (self.tag, form.start)) + form.close = XML("%s</%s>" % (form.close, self.tag)) + self.custom.form = form + self.components = [TABLE(*xfields)] def accepts( @@ -579,7 +627,6 @@ self.vars.id = self.table.insert(**fields) return ret - class SQLTABLE(TABLE): """ @@ -673,7 +720,10 @@ def form_factory(*fields, **attributes): + """ + generates a SQLFORM for the given fields. + + Internally will build a non-database based data model to hold the fileds. + """ return SQLFORM(SQLDB(None).define_table('no_table', *fields), **attributes) - - 2009/6/4 Hans Donner <hans.don...@pobox.com>: > Seems to be it, thanks. > > 2009/6/4 David Marko <dma...@tiscali.cz>: >> >> Do you mean something like this? http://web2py.com/AlterEgo/default/show/205 >> >> David >> >> On 4 čvn, 11:12, Hans Donner <hans.don...@pobox.com> wrote: >>> Currently SQLFORM renders a complete table for the fields provided (or >>> all) for a db.table, and does some other magic as well. >>> >>> Would love to reuse the magic, but be in more control of the >>> rendering. Eg, would like to specify what fields are placed where, and >>> if they should include labels or not etc. >>> What fields are to be rendered where should be easiliy done form the >>> template. >>> >>> (the underlying table is quite big, and when all is listed like it is >>> now it's too overwhelming. A different layout makes it far more better >>> (esp when throwing in some ajax), eg having some sort of matrix, >>> having some labels only for rows and columns vs for every field) >>> >>> Any suggestions? >>> I'm digging in the code, and find that the fields and the rendering of >>> the fields are glued together and not easy to seperate/re-use. Might >>> be that I'm missing something here. >>> >>> Would like to do something like: >>> >>> {{=form.start}} >>> <table> >>> <th><td></td><td>header 1</td><td>header 2</td><td>header 3</td></tr> >>> <tr><td>{{=form.field['field1'].label</td><td>{{=form.field['field1']</td>< >>> td>{{=form.field['field2']</td><td>{{=form.field['field5']</td></tr> >>> </table> >>> <div> >>> <span>{{=form.field['field3'].label}}: {{=form.field['field3']}}</span> >>> </div> >>> <div> >>> {{=form.submit}} >>> </div> >>> {{=form.end}} >>> >>> where the fields have the currently shown widgets in place without the >>> need for me to construct these... >> >> >> > --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "web2py Web Framework" group. To post to this group, send email to web2py@googlegroups.com To unsubscribe from this group, send email to web2py+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/web2py?hl=en -~----------~----~----~----~------~----~------~--~---