Iceberg,

Thanks, you were right. I didn't think I had to know/care about
whether requests were POST or GET with web2py (and indeed had to
refresh my memory of what the difference was - I'm new to this whole
interweb thing), as far as I was concerned I was just calling
functions within controllers.

Turns out that the function with a self-submitting form is called
using GET when first called, then POST on clicking submit (I don't
remember reading this anywhere). The addition of a field in the form
with the same name as a variable passed in the GET request variables
resulted in those two variables 'merging' into a list as far as
request.vars was concerned. A tad evil I say, but I'm sure it was the
best design option available at the time :-)

I'm now questioning whether I'd ever want to use request.vars instead
of explicitly specifying request.get_vars and request.post_vars, I'll
look out for whether I can/should apply this as I go...


On Jun 2, 4:13 pm, Iceberg <[email protected]> wrote:
> Did not look into your code. But this kind of situation usually is
> caused by a form receives variables from both GET and POST. In this
> case, request.vars.myvar=['blah', 'blah'], but
> request.get_vars.myvar='blah', and request.post_vars.myvar='blah'.  So
> you can choose to use only one of it.
>
> On Jun2, 9:15pm, Andrew Buchan <[email protected]> wrote:
>
>
>
> > Hello,
>
> > I've had this issue before, where a string which is passed as part of
> > request.vars somehow becomes a list when the form is submitted. The
> > way I got round it at the time was by doing:
>
> > if isinstance(thread_id, list):
> >     thread_id = thread_id[0]
>
> > However, that just doesn't feel right, and will only work where the
> > value never changes (i.e. I can assume that all items in the list have
> > the same value so [0] is as good as any), and more to the point, it
> > doesn't address why this is happening in the first place.
>
> > I tried the suggestion in post 17355 of this mailing group which seems
> > to suggest explicitly passing the vars on submit by adding the
> > following to the submit button:
>
> >  _action=URL(r=request,args=request.args)
>
> > However, that doesn't work either.
>
> > I've posted some code below where this is happening to the variable
> > "thread_id", if you look at the 8th & 9th line of function
> > addreplacementpage() you'll see that I test whether the variable is a
> > list or not, and it proves positive only when the form is submitted,
> > i.e. the function goes round the loop a second time (self-submitting
> > form).
>
> > Has anyone else experienced this or have a solution to the problem, or
> > even better: advice on how to figure out what's going on in these kind
> > of situations?
> > Also, feel free to bash the code, constructively...
>
> > regards,
>
> > Andy.
> > -------------
>
> > def addreplacement():
> >     #Call this function from other pages, it will initialise the
> > PartLists and SelectedParts session
> >     #variables if required, generate a thread_id and then redirect to
> > addreplacementpage function below.
> >     #These two session variables store the partlist and currently-
> > selected-item-in-partlist(for delete/edit purposes)
> >     #for the replacement currently being worked on (either newly
> > raised or amended)
> >     #The 'thread_id' var is used to allow multiple replacements to be
> > edited within the same session,
> >     #so for the replacement currently being edited use
> > session.PartLists[thread_id] to obtain prt list
> >     #and session.SelectedParts[thread_id] to obtain selected part.
> >     Complaint_Base_id  = request.vars.record
> >     title = 'Complaint Raised'
> >     if not (Complaint_Base_id ):
> >         return ComplaintSystem.__ShowSimplePage(globals(),
> > dict(message = "Record id was not supplied with request." ,
> > title=title))
> >     thread_id = int(uuid.uuid4())
> >     if not session.PartLists:
> >         session.PartLists = dict()
> >     session.PartLists[thread_id] = dict()
> >     if not session.SelectedParts:
> >         session.SelectedParts = dict()
> >     session.SelectedParts[thread_id] = -1
> >     redirect(URL(r=request, f='addreplacementpage',
> > vars={'record':Complaint_Base_id, 'thread_id':thread_id}))
>
> > def addreplacementpage():
> >     #This must only ever be called by function 'addreplacement'
> >     title = 'Complaint Raised'
> >     Complaint_Base_id  = request.vars.record
> >     thread_id = request.vars.thread_id
> >     assert(Complaint_Base_id )
> >     assert(thread_id)
> >     if isinstance(thread_id, list):
> >         return 'its a list!!!!!'
> >     response.view = 'Complaints/AddReplacement.html'
> >     response.title = title
> >     Table = db.Replacement
> >     form = GenerateReplacementForm( thread_id = thread_id )
> >     if form.accepts(request.vars, session):
> >         FieldValues = dict()
> >         for f in Table.fields:
> >             if form.vars.has_key(f):
> >                 FieldValues[f] = form.vars[f]
> >         FieldValues['Complaint_Base_id'] = Complaint_Base_id
> >         ReplacementId = Table.insert(**FieldValues)
> >         for key, value in session.PartLists[thread_id].items():
> >             db.Replacement_Part.insert(Replacement_id=ReplacementId,
> > Row_Index=key, Part_Number=value[0], Description=value[1],
> > Cost=value[2], Quantity=value[3])
> >         return ComplaintSystem.__ShowSimplePage(globals(),
> > dict(message='New record created', title='Record Created', links =
> > links))
> >     return dict(form = form, id = Complaint_Base_id )
>
> > def GenerateReplacementForm( thread_id , Rec_ID = None):
> >     Table = db.Replacement
> >     Fields = list(db.Replacement.fields)
> >     for i in ['Complaint_Base_id', 'Status', 'Date_Authorised',
> > 'Project_Coordinator']:
> >         Fields.remove(i)
> >     if Rec_ID :
> >         form = SQLFORM(Table, record = Rec_ID , showid=False, fields =
> > Fields)
> >     else:
> >         form = SQLFORM(Table, fields = Fields)
>
> >     form.custom.submit = INPUT(_type="submit", _value="Submit",
> > _action=URL(r=request,args=request.args))
>
> >     ajaxAddPart = "ajax('%s', %s, 'partfielderrors');ajax('%s',
> > %s,'target');" % \
> >         (URL(r=request,f='validatepart'), PartFieldsString,
> > URL(r=request, f='addpart'), PartFieldsString)
> >     innertable = TABLE(
> >         TR(
> >             TD(
> >                 TABLE(
> >                     TR(TD(B('Add Part:')), TD(INPUT(_type='hidden',
> > _id='thread_id', _name='thread_id', _value=thread_id)), TD()),
> >                     TR(
> >                         TD(LABEL('Part No')),
> > TD(LABEL('Description')), TD(LABEL('Cost')), TD(LABEL('Quantity'))),
> >                     TR(
> >                         TD(INPUT(_type="text", _id='partno',
> > _name='partno', _class='partnofield' )),
> >                         TD(INPUT(_type='text', _id='description',
> > _name='description', _class='descriptionfield' )),
> >                         TD(INPUT(_type='text', _id='cost',
> > _name='cost', _class='numericfield')),
> >                         TD(INPUT(_type='text', _id='quantity',
> > _name='quantity', _class='numericfield')))
> >                     )
> >                 )
> >             ),
> >         TR(
> >             TD(
> >                 TABLE(
> >                     TR(
> >                         TD(INPUT(_type='button', _value='Add part',
> > _onclick=ajaxAddPart)),
> >                         TD(DIV('', _id='partfielderrors',
> > _class='error' ))
> >                         )
> >                     )
> >                 )
> >             ),
> >         _class='tablewithborder'
> >     )
> >     outtertable = TABLE(
> >         TR(TD(B('Replacement Parts:'))),
> >         TR(TD(DIV(__refreshtable(thread_id), _id='target'))),
> >         TR(TD(innertable )),
> >         _class='tablewithborder')
>
> >     form[0][12].insert(1, TR(TD(), TD(outtertable)))
> >     return form
>
> > def __refreshtable(thread_id):
> >     if isinstance(thread_id,list):
> >         thread_id = thread_id[0]
> >     if session.PartLists and  session.PartLists.has_key(thread_id):
> >         partlist = session.PartLists[thread_id]
> >     else:
> >         partlist = dict()
>
> >     if len(partlist.items()) > 0:
> >         table = TABLE(TR(TD(INPUT(_type='hidden', _id='thread_id',
> > _value=thread_id)), TD(LABEL('Part No')), TD(LABEL('Description')),
> > TD(LABEL('Cost')), TD(LABEL('Quantity'))),
> > _class='tablewithinnerborder')
> >         rowcnt = 0
> >         sel_func = URL(r=request,f='selectpart')
> >         ajaxRemovePart = "ajax('%s', ['thread_id'], 'target');" %
> > URL(r=request, f='removepart')
> >         ajaxeditpart = "ajax('%s',['thread_id'],'target');" %
> > URL(r=request,f='editpart')
> >         Total = 0.0
> >         IndicesList = list(partlist .iterkeys())# use this so we have
> > parts listed in order they were added...
> >         IndicesList.sort()
> >         for key in IndicesList:
> >             value = partlist[key]
> >             rowcnt += 1
> >             idstr = 'partselection%s' % key
> >             fieldsString = "['%s', 'thread_id']" % idstr
> >             cost = value[2]
> >             quantity = value[3]
> >             table.insert(rowcnt , TR(
> >                 TD(INPUT(_type='radio', _name='partselect', _id =
> > idstr , _value = key, _onclick="ajax('%s', %s);" %(sel_func ,
> > fieldsString))),
> >                 TD(INPUT(_type='text', _disabled=True,
> > _value=value[0], _class='partnofield' )),
> >                 TD(INPUT(_type='text', _disabled=True,
> > _value=value[1], _class='descriptionfield' )),
> >                 TD(INPUT(_type='text', _disabled=True, _value=cost ,
> > _class='numericfield')),
> >                 TD(INPUT(_type='text', _disabled=True,
> > _value=quantity , _class='numericfield'))
> >             ))
> >             Total += quantity * cost
> >         table.insert(rowcnt + 1, TR(
> >             TD(),
> >             TD(),
> >             TD(LABEL('Total Replacement Cost:')),
> >             TD(INPUT(_type='text', _disabled=True, _value=Total,
> > _class='numericfield')),
> >             TD())
> >         )
> >         table.insert(rowcnt + 2, TR(
> >             TD(),
> >             TD(INPUT(_type='button', _value='Remove Selected',
> > _onclick=ajaxRemovePart )),
> >             TD(INPUT(_type='button', _value='Edit Selected',
> > _onclick=ajaxeditpart )),
> >             TD(INPUT(_type='hidden', _id='dummy')),
> >             TD())
> >      ...
>
> read more »

Reply via email to