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 »

