give me some time to digest this. could email it to me again. the
indentation is messed up.

On Oct 14, 5:58 am, billf <[EMAIL PROTECTED]> wrote:
> My objective is to be able to hand-code my own view containing a form
> that I can layout exactly as I want but retain the benefits of
> accepts() re validation and db updating.
>
> I found 2 obstacles with web2py out-of-the box:
> 1) In my view (I have less than 1 week of python), I did not have easy
> access to the latest version of a field: defaults could be in
> form.record.my_field (but not for a new record) but if the user has
> input data then it is in form.vars.my_field.  I wanted a consistent
> source and the only place is form.components but extracting the values
> in the view seems difficult due to the nested nature of components.
>
> 2) For dropdown lists, the value is not enough.  I want the whole
> <select><options> etc including which option is selected.
>
> If I can achieve the above there are a couple of other requirements:
> 3) For completeness, support for the session/formkey mechanism and any
> other hidden fields that may be specified.
>
> 4) If I display the whole control (as in 2) above), I don't want any
> pre-formatted errors.  I can get the necessary info from form.errors.
>
> With my solution, the usage is as follows:
> - in a controller, after the SQLFORM(db.recipe) or FORM(whatever) is
> created add form.customview=True
>
> - in a view, after the <form> tag for your custom form add {{=form}} -
> this will create a Storage called 'latest' in FORM with a 'value' and
> a 'component' for each fieldname and return the following:
> <!-- custom view -->
> <input value="130911852535" type="hidden" name="_formkey" />
> <input value="recipe" type="hidden" name="_formname" />
> ... plus any other hidden INPUTS specified in the form
>
> - if you just want the latest value for a fieldname 'name' then code
> something like
> <input type="text" name="name" value="{{=form.latest.name['value']}}"/
>
>
>
> - if you just want the whole control then code something like
> {{=form.latest.name['component']}} to get
> <input type="text" class="string" name="name" value="Cornish Pasty"
> id="recipe_name" />"
>
> - or, where the field has IS_IN_SET, code
> {{=form.latest.type['component']}} to get
> <select class="string" name="type" id="recipe_type"><option
> value="A">accompaniment</option><option value="C">component</
> option><option value="R" selected="selected">recipe</option></select>
>
> So, assuming anyone's still interested, what changes did I make to the
> web2py code?  Well, it's all in html.py and makes use of a new Storage
> attribute called 'latest' added to FORM if customview is present and
> True:
>
> a) replace the existing FORM.xml() method with the following:
>     def xml(self):
>         if self.customview and self.customview==True:
>             self._latestdata()
>             # return hidden INPUTs in response to {{=form}}
>             hidden=''
>             field=self.latest['hidden']
>             for component in field['component']:
>                 hidden+=component.xml()+'\n'
>             return '<!-- custom view -->\n'+hidden
>         else:
>             # exactly the same as old xml() except hidden logic in
> common method _hiddendata([])
>             newform=FORM(*self.components,**self.attributes)
>             self._hiddendata(newform.components)
>             return DIV.xml(newform)
>     # common method for creating/storing formkey and creating hidden
> INPUTs - taken from original xml()
>     def _hiddendata(self, components):
>         if self.session!=None:
>             _formkey='_formkey[%s]' % self.formname
>             key=self.session[_formkey]=str(random.random())[2:]
>
> components.append(INPUT(_type='hidden',_name='_formkey',_value=key))
>         if self.formname!=None:
>             components.append(INPUT(_type='hidden',_name='_formname',\
>                            _value=self.formname))
>         if self.attributes.has_key('hidden'):
>             hidden=self['hidden']
>             for key,value in hidden.items():
>
> components.append(INPUT(_type='hidden',_name=key,_value=value))
>     # create the Storage to hold value and component for each
> fieldname + one for 'hidden' INPUTs
>     def _latestdata(self):
>         self.latest=Storage()
>         components=[]
>         self._hiddendata(components)
>
> self.latest['hidden']={'value':'hidden','component':components}
>         for component in self.components:
>             component._latestdata(self.latest)
>
> a) add the following to DIV to find the required component and store
> in latest Storage
>     def _latestdata(self, latest):
>         # the following code checks whether the component can have
> user input and
>         # if true stores the value and component using the latestitem
> helper
>         # if false iterates through child components
>         if self.attributes.has_key('_value') and\
>            self.attributes.has_key('_name'):
>
> latest[self.attributes['_name']]=self.latestitem(self.attributes['_value'],self)
>         elif isinstance(self,SELECT) and\
>            self.attributes.has_key('_name'):
>
> latest[self.attributes['_name']]=self.latestitem(None,self)
>         elif isinstance(self,TEXTAREA) and\
>            self.attributes.has_key('value') and\
>            self.attributes.has_key('_name'):
>             value=self.attributes['value']
>             if value==None: value=''
>
> latest[self.attributes['_name']]=self.latestitem(value,self)
>         elif self.components:
>             for c in self.components:
>                 if hasattr(c,'_latestdata'): c._latestdata(latest)
>     # store value and component ensuring any errors are ignored
>     def latestitem(self, value, component):
>         component.errors=None
>         return {'value':value,'component':component}
>
> That's it - it all seems to work a treat. All feedback gratefully
> received (this is where Massimo tells me it could all have been done
> with 2 lines of python and a regex) :-)
>
> Bill
--~--~---------~--~----~------------~-------~--~----~
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 [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/web2py?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to