From: Randall R. <ra...@ra...> - 2003-09-17 23:24:22
|
Hi, all. I've been using dAlchemy's FormKit, and until now, all has been well. Today, I was writing a servlet to display multiple forms, and I start getting some weird behavior. I need to create a number of forms that depend on how many objects there are to modify. If there are 3, there need to be 3 forms, one of which will be used. At first, my servlets were creating extra forms for each form I create in awake() on every refresh of the page. This suggests that the forms themselves were persisting through sleep(), so I added a statement to delete self._forms, but now the form never seems to be successful. Is there a right way to handle variable numbers of anonymous forms with FormKit, or should I try to shove all possible objects into one form? -- Randall Randall <ra...@ra...> "When you advocate any government action, you must first believe that violence is the best answer to the question at hand." -- Allen Thornton |
From: Matt F. <ma...@da...> - 2003-09-18 16:54:43
|
Randall Randall wrote: > I need to create a number of forms that depend on how > many objects there are to modify. If there are 3, there > need to be 3 forms, one of which will be used. This should be no problem; we do it all the time. Just make sure that you're using different submit methods (actions) for each one. > At first, my servlets were creating extra forms for > each form I create in awake() on every refresh of the > page. This suggests that the forms themselves were > persisting through sleep(), so I added a statement to > delete self._forms, but now the form never seems to be > successful. There is a reset forms method that is typically called from sleep() (but can be called by you whenever you like)-- make sure that you haven't accidentally removed it. > Is there a right way to handle variable numbers of > anonymous forms with FormKit, or should I try to > shove all possible objects into one form? > Look in the examples for the "MultiFormExample.py" and follow that precedent. -- Matt Feifarek dAlchemy |
From: Randall R. <ra...@ra...> - 2003-09-18 18:39:34
|
On Thursday, September 18, 2003, at 12:54 PM, Matt Feifarek wrote: > Randall Randall wrote: >> I need to create a number of forms that depend on how >> many objects there are to modify. If there are 3, there >> need to be 3 forms, one of which will be used. > > This should be no problem; we do it all the time. Just make sure that > you're using different submit methods (actions) for each one. That seems tricky; I'd had every form using the same submit method and the method was cycling through every form in self._forms to find the successful one that had called it. So, to do this, I'd need to define a generic method and use setattr to set the name of each copy to the name of the submit button as it's generated? >> At first, my servlets were creating extra forms for >> each form I create in awake() on every refresh of the >> page. This suggests that the forms themselves were >> persisting through sleep(), so I added a statement to >> delete self._forms, but now the form never seems to be >> successful. > > There is a reset forms method that is typically called from sleep() > (but can be called by you whenever you like)-- make sure that you > haven't accidentally removed it. I use the FormKitMixIn, and self.resetForms() , but my problem hasn't been the contents being uncleared, but extra forms. That is, if I use f = Form.Form() in awake(), the second load has two forms dumped by for form in self._forms: wr( form.dump() ) and the third time I reload the page, I have three forms on it, etc. I hope that using different submit methods, as mentioned above, fixes this. :) >> Is there a right way to handle variable numbers of >> anonymous forms with FormKit, or should I try to >> shove all possible objects into one form? >> > Look in the examples for the "MultiFormExample.py" and follow that > precedent. Those are named forms, though. The example didn't seem to apply for a variable number of forms, only a static number. -- Randall Randall <ra...@ra...> "When you advocate any government action, you must first believe that violence is the best answer to the question at hand." -- Allen Thornton |
From: Randall R. <ra...@ra...> - 2003-09-18 19:48:47
|
On Thursday, September 18, 2003, at 02:39 PM, Randall Randall wrote: > On Thursday, September 18, 2003, at 12:54 PM, Matt Feifarek wrote: >> Randall Randall wrote: >>> I need to create a number of forms that depend on how >>> many objects there are to modify. If there are 3, there >>> need to be 3 forms, one of which will be used. >> >> This should be no problem; we do it all the time. Just make sure that >> you're using different submit methods (actions) for each one. > > That seems tricky; I'd had every form using the same submit method > and the method was cycling through every form in self._forms to > find the successful one that had called it. > > So, to do this, I'd need to define a generic method and use > setattr to set the name of each copy to the name of the > submit button as it's generated? It turns out that this works for me. Those extra forms still crept into self._forms, but simply checking to see whether the new submit method was registered for each iteration of creating a form was sufficient to weed it out. I'm still not very clear on the "recommended" way to create forms in awake(), since the way I'm doing it, by manipulating self._forms, doesn't seem very natural. If this is the right way, I can create an example for your Examples folder. If not, and you find the time before the next release, an example of a form created in awake() would be helpful, I think. :) Thanks! -- Randall Randall <ra...@ra...> "When you advocate any government action, you must first believe that violence is the best answer to the question at hand." -- Allen Thornton |
From: Matt F. <ma...@da...> - 2003-09-19 19:57:26
|
Randall Randall wrote: > > On Thursday, September 18, 2003, at 02:39 PM, Randall Randall wrote: > >> On Thursday, September 18, 2003, at 12:54 PM, Matt Feifarek wrote: >> >>> Randall Randall wrote: >>> >>>> I need to create a number of forms that depend on how >>>> many objects there are to modify. If there are 3, there >>>> need to be 3 forms, one of which will be used. >>> >>> >>> This should be no problem; we do it all the time. Just make sure >>> that you're using different submit methods (actions) for each one. >> >> >> That seems tricky; I'd had every form using the same submit method >> and the method was cycling through every form in self._forms to >> find the successful one that had called it. >> >> So, to do this, I'd need to define a generic method and use >> setattr to set the name of each copy to the name of the >> submit button as it's generated? > > > It turns out that this works for me. Those extra forms still > crept into self._forms, but simply checking to see whether > the new submit method was registered for each iteration of > creating a form was sufficient to weed it out. Oh, I see what you mean, now. Since you don't know how many forms you'll have, the name of the submit method isn't necessarily predictable. Yes, I'd stick with one submit method, and just make it a bit more sophisticated about how it does processing. Grabbing "__formID__" from the posted fields, and corresponding that to self._forms should help. > I'm still not very clear on the "recommended" way to create > forms in awake(), since the way I'm doing it, by manipulating > self._forms, doesn't seem very natural. If this is the right > way, I can create an example for your Examples folder. If > not, and you find the time before the next release, an example > of a form created in awake() would be helpful, I think. :) There's nothing special about awake, really. It's just a method, like any other. The fact that it's called every page load may lead to an explanation about why you're getting extra forms, but it's certainly not designed to work that way. That having been said, if you come up with a cool example, of course we're interested. |
From: Randall R. <ra...@ra...> - 2003-09-19 19:53:55
|
On Thursday, September 18, 2003, at 11:03 PM, Matt Feifarek wrote: > Randall Randall wrote: >> It turns out that this works for me. Those extra forms still >> crept into self._forms, but simply checking to see whether >> the new submit method was registered for each iteration of >> creating a form was sufficient to weed it out. > > Oh, I see what you mean, now. Since you don't know how many forms > you'll have, the name of the submit method isn't necessarily > predictable. Yes, I'd stick with one submit method, and just make it a > bit more sophisticated about how it does processing. Grabbing > "__formID__" from the posted fields, and corresponding that to > self._forms should help. Yeah, I finally opted not to use the Mix-in machinery, although it's mixed into my SitePage, for convenience. Setting a preAction method took care of that, though. It might be that I'll be able to do it cleanly with the Mix-in, but right now I'm going to leave it as it is: working. :) >> I'm still not very clear on the "recommended" way to create >> forms in awake(), since the way I'm doing it, by manipulating >> self._forms, doesn't seem very natural. If this is the right >> way, I can create an example for your Examples folder. If >> not, and you find the time before the next release, an example >> of a form created in awake() would be helpful, I think. :) > > There's nothing special about awake, really. It's just a method, like > any other. The fact that it's called every page load may lead to an > explanation about why you're getting extra forms, but it's certainly > not designed to work that way. > > That having been said, if you come up with a cool example, of course > we're interested. I'll try to see how I can generalize what I did into an example, and send it along. Thanks! -- Randall Randall <ra...@ra...> "When you advocate any government action, you must first believe that violence is the best answer to the question at hand." -- Allen Thornton |
From: Aaron H. <aaron@MetroNY.com> - 2003-09-19 20:02:23
|
> I'm still not very clear on the "recommended" way to create > forms in awake(), since the way I'm doing it, by manipulating > self._forms, doesn't seem very natural. If this is the right > way, I can create an example for your Examples folder. If > not, and you find the time before the next release, an example > of a form created in awake() would be helpful, I think. :) > > Thanks! Not sure if I am doing it the "correct way" but I have a page where the form is generated on the fly each time. The form only needs to exist if it needs to be rendered for the user, or if it needs to be validated. I am not using the mixin and doing all the processing explicitly. So I have base class w/ def initForm(self): '''Initialize the base form. This should be the same for all classes, there is a hook to init2 to add controls specific to the report being created.''' f1 = self.form1 = Form.Form( ) f1._setFormID(self.reportID) f1.addField( Fields.SelectField('rowsPerPage', label="Records per Page") ) ..... Then if the user send forminfo I do: def showReport(self) self.initForm() fields = self.request().fields() self.form1.process( fields ) # save the user values currentValues = {} for f in self.form1.fields(): currentValues[f.name()] = f.value() formValid = self.form1.isSuccessful() if not formValid: f1 = self.form1 put back the user values f1.seed(currentValues) self.writeForm('Error') else: self.writeReportHTML() This has the disadvantage of building up the form class each run. You may want to use some instance caching in initForm to save the form between runs, and then call something to .sleep each form in servlet.sleep. There are some good examples of this type of caching relating to Cheetah templates. -Aaron |
From: Matt F. <ma...@da...> - 2003-09-19 19:44:41
|
Aaron Held wrote: > >> I'm still not very clear on the "recommended" way to create >> forms in awake(), since the way I'm doing it, by manipulating >> self._forms, doesn't seem very natural. If this is the right >> way, I can create an example for your Examples folder. If >> not, and you find the time before the next release, an example >> of a form created in awake() would be helpful, I think. :) >> >> Thanks! > > > Not sure if I am doing it the "correct way" but I have a page where > the form is generated on the fly each time. We had a pretty serious goal when designing FormKit for there not to be a "correct" way. The MixIn is good for beginners to get started, but we wanted the form mechanics to be useful without that. We even use FK without servlets now and then... basically, it's just an html tag builder and value parser... much ado about nothing. > Then if the user send forminfo I do: > > def showReport(self) > self.initForm() > fields = self.request().fields() > self.form1.process( fields ) > # save the user values > currentValues = {} > for f in self.form1.fields(): > currentValues[f.name()] = f.value() The self.form1.values() method does what those last two lines do ;-) > formValid = self.form1.isSuccessful() > if not formValid: > f1 = self.form1 > put back the user values > f1.seed(currentValues) > self.writeForm('Error') > else: > self.writeReportHTML() > You shouldn't have to seed the form; the values should still be in there, after they were processed. Unless you call a .reset() or something, the inputs are still there (as are the defaults, if any). > This has the disadvantage of building up the form class each run. > You may want to use some instance caching in initForm to save the form > between runs, and then call something to .sleep each form in > servlet.sleep. You can certainly do that, but it shouldn't be too much overhead; FK is basically just making strings. |
From: Aaron H. <aaron@MetroNY.com> - 2003-09-22 14:12:17
|
>> # save the user values >> currentValues = {} >> for f in self.form1.fields(): >> currentValues[f.name()] = f.value() > > > The self.form1.values() method does what those last two lines do ;-) Thanks >> formValid = self.form1.isSuccessful() >> if not formValid: >> f1 = self.form1 >> put back the user values >> f1.seed(currentValues) >> self.writeForm('Error') >> else: >> self.writeReportHTML() >> > You shouldn't have to seed the form; the values should still be in > there, after they were processed. Unless you call a .reset() or > something, the inputs are still there (as are the defaults, if any). I build the form class for each run, w/o seeding the form it renders w/ blank values. -- -Aaron http://www.MetroNY.com/ "I don't know what's wrong with my television set. I was getting C-Span and the Home Shopping Network on the same station. I actually bought a congressman." - Bruce Baum |
From: Randall R. <ra...@ra...> - 2003-09-19 19:55:22
|
On Friday, September 19, 2003, at 10:21 AM, Aaron Held wrote: > > This has the disadvantage of building up the form class each run. > > You may want to use some instance caching in initForm to save the form > between runs, and then call something to .sleep each form in > servlet.sleep. My servlet currently builds any number of forms for each run. :( I may eventually implement some caching of form classes, but I'm not sure if that'll be helpful. When the servlet is accessed by "Bob", it may have 2 forms, and by "Cecil", 17 forms, so any caching I do would have to ignore extras. -- Randall Randall <ra...@ra...> "When you advocate any government action, you must first believe that violence is the best answer to the question at hand." -- Allen Thornton |
From: Matt F. <ma...@da...> - 2003-09-19 20:06:39
|
Randall Randall wrote: >> This should be no problem; we do it all the time. Just make sure that >> you're using different submit methods (actions) for each one. > > That seems tricky; I'd had every form using the same submit method > and the method was cycling through every form in self._forms to > find the successful one that had called it. That should be fine; I'd argue that it makes your code simpler to debug and read if each "action" has its own method, but there's no reason that you can't iterate through your forms in your submit method, and find which one has been posted. FYI, each form has a hidden field called "__formID__" which allows the form processor to know which form that has been posted. You can use that, if you want. > So, to do this, I'd need to define a generic method and use > setattr to set the name of each copy to the name of the > submit button as it's generated? I'm not sure what you mean; look up the way actions work in webkit; it does getattr for you already, associating "actions" (based on submit buttons) with methods. Works great. > I use the FormKitMixIn, and self.resetForms() , but my > problem hasn't been the contents being uncleared, but > extra forms. That is, if I use > f = Form.Form() > in awake(), the second load has two forms dumped by > for form in self._forms: > wr( form.dump() ) > > and the third time I reload the page, I have three > forms on it, etc. I hope that using different submit > methods, as mentioned above, fixes this. :) > Unless you do self.addForm( f ) on your FormKitMixIn derived page, this shouldn't happen. You must be doing something wrong. Declaring a form in awake doesn't do anything; it just makes a class instance. If you don't register it to the servlet with self.addForm() or store it in self, it will be destroyed when the method is over. Standard python stuff. >>> Is there a right way to handle variable numbers of >>> anonymous forms with FormKit, or should I try to >>> shove all possible objects into one form? >> >> Look in the examples for the "MultiFormExample.py" and follow that >> precedent. > > Those are named forms, though. The example didn't seem > to apply for a variable number of forms, only a static > number. There's nothing special about form objects (or field objects for that matter); they're just python class instances. You can do whatever you want with them... stick them on the right side of dictionary, in a list, in tuple, whatever. We did happen to name them, but you could also just stack them up in a list, and add and delete them as you go. If you want them to be processed automatically (you can process them manually of course) you need to add them to the servlet via the self.addForm(). We don't have a companion self.deleteForm() which may seem stupid. You can certainly dig into the _forms container, if you wish. What you are doing is a little more sophisticated than a typical servlet example. You don't have to use the MixIn, so maybe you shouldn't. You can look in "NoMixInExample" or even "NoServletExample" to see how FK works, and maybe it will be easier for you to handle the processing manually. It's no problem, really. I hope this helps. I could look at your code, if you're still stuck. |