Question

My question may be the same as this, but the suggested answer didn't seem to help (or I didn't understand it correctly): Pylons FormEncode @validate decorator pass parameters into re-render action

I have a simple form that takes a required querystring (id) value, uses that as a hidden form field value, and validates the posted data. The controller looks like this:

class NewNodeForm(formencode.Schema):
  parent_id = formencode.validators.Int(not_empty = True)
  child_name = formencode.validators.String(not_empty = True)

def newnode(self, id):
  c.parent_id = id
  return render('newnode.html')

@validate(schema=NewNodeForm(), form='newnode')
def createnode(self):
  parentId = self.form_result.get('parent_id')
  childName = self.form_result.get('child_name')
  nodeId = save_the_data(parentId, childName)
  return redirect_to(controller = 'node', action = 'view', id = nodeId)

and the form is very basic:

<form method="post" action="/node/createnode">
  <input type="text" name="child_name">
  <input type="hidden" value="${c.parent_id}" name="parent_id">
  <input name="submit" type="submit" value="Submit">
</form>

Everything works fine if the validation passes, but if it fails, newnode can't be called because id isn't passed back. It throws TypeError: newnode() takes exactly 2 arguments (1 given). Simply defining as newnode(self, id = None) gets around this problem, but I can't do that as the id is required by the logic.

This seems so simple, but what am I missing?

Was it helpful?

Solution

If you are using an id arg in your newnode my preference would be to use the same arg in it's related createnode function. Adapt your post url to use an id, and you wont need to hidden the parent_id because it is now part of the url.

<form method="post" action="/node/createnode/${request.urlvars['id']}">
  <input type="text" name="child_name">
  <input name="submit" type="submit" value="Submit">
</form>

OTHER TIPS

When validation failed the validate decorator call you newnode with modified request object, but all GET/POST arguments must be not changed

def newnode(self, id=None):
  c.parent_id = id or request.params.get('parent_id')
  return render('newnode.html')
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top