Re: [Zope3-Users] z3c.form: Data Manager - getting value via dm.query() instead of dm.get()
On Wednesday 13 August 2008, Hermann Himmelbauer wrote: > The problem is, that if the dictionary does not contain all fields, an > error is raised. The reason for this error lies in line 97 in > z3c.form.widget: The value is retrieved via the get() function (which does > a dict.get()) and thus fails. That is correct. My initial assumption was that a dictionary should define all available fields, much like we expect a class instance to have all attributes around. > The solution for this problem would be to replace the datamanager.get() by > datamanager.query(), as this would return the default field value. > However, this may break other projects, therefore I would suggest to: > > - Introduce some form option such as "ContextQuery=True/False" > - Either use dm.get() or .query() regarding to this option > > What's your opinion on this? Would this be a decent solution? Looking at the code, I would change the call in widget.py line 97 to a query() call. There is another dm.get() call in the code that also would be changed. This feature could be added to the 1.9.0 release. Feel free to check in a patch. Regards, Stephan -- Stephan Richter Web Software Design, Development and Training Google me. "Zope Stephan Richter" ___ Zope3-users mailing list Zope3-users@zope.org http://mail.zope.org/mailman/listinfo/zope3-users
Re: [Zope3-Users] z3c.form: Data Manager - getting value via dm.query() instead of dm.get()
Hi Hermann Hi Hermann > Betreff: Re: AW: AW: AW: [Zope3-Users] z3c.form: Data Manager > - getting value via dm.query() instead of dm.get() [...] > > Such a search session object could look like: > > > > class ISearchSession(ISession): > > """Message filter session.""" > > > > searchText = zope.schema.TextLine( > > title=Search text', > > description=u'The search text', > > default=u'', > > required=False) > > > > class SearchSessioon(Session): > > _spd = None > > > > @Lazy > > def spd(self): > > return self.__getitem__('SEARCH_SESSION_KEY') > > > > @apply > > def searchText(): > > def get(self): > > return self.spd.get('searchText', u'') > > def set(self, searchText): > > self.spd['searchText'] = searchText > > return property(get, set) > > Is the parent object Session/ISession the one from > zope.session? How does it connect to the persistent Session > object? And what is "@Lazy"? Yes, from zope.session.session import Session Lazy will cache your method result and return them again for future access. See: from zope.cachedescriptors.property import Lazy > Yes, that's a possibility, but it would force me to write: > > - An property for every field. > - A class for every search view. > > All in all that's around ~ 200 lines of code for 5 search > forms with appr. > 5 fields each, compared to appr. 10 lines of code in my solution. I see > > I allways use such a session implementation because it > abstracts what > > you need, uses schema fields, offers built in defaults and > works well > > with z3c.form. > > Yes, thanks for the code snippet, it's interesting and a > clean solution. > > > Note; I'm still not 100% sure if the get() or query() usage in > > applyChanges is right or wrong. I hope to find time to deep > into that > > in the near future. > > > > But I think nobody will understand the concept if we > implement a form > > property for use get or query in applyChanges. > > Yes, that may be true. Hmmm... > > > Hope the session concept works for you till someone > agrees/checks the > > get/query useage. > > Well, I have two more possibilities until this is sorted out entirely: > > 1) Monkey patch z3c.form.DictionaryField.get() and let it > return interfaces.NOVALUE > 2) Write an register my own data manager to overcome this. I think a custom data manager is the way to go for you. Probably a session property handling needs something different then a simple dict or a context data manager. Regards Roger Ineichen > Thanks again for help, > Best Regards, > Hermann > > -- > [EMAIL PROTECTED] > GPG key ID: 299893C7 (on keyservers) > FP: 0124 2584 8809 EF2A DBF9 4902 64B4 D16B 2998 93C7 > > > ___ Zope3-users mailing list Zope3-users@zope.org http://mail.zope.org/mailman/listinfo/zope3-users
Re: [Zope3-Users] z3c.form: Data Manager - getting value via dm.query() instead of dm.get()
> Hi Hermann >> So, it may happen, that not all fields are filled out, >> therefore key/value pairs may be missing. If that happens, >> the widget routine throws an error. >> If I manage to overcome this error (e.g. by replacing the >> get() through >> query() routine in z3c.form.widget), my form works. > > I understand. Ther must be something wrong. > Take a look at the AddForm implementation this one uses > ignoreContext = True. This forces to not store the values > to the object. Because it doesn't use applyChanges like > the EditForm does. > > For a SearchForm, you can use extractData offered from > the form and do what every you need to do with the extracted > form values. e.g. store them into a session. You can setup > the widgets with this values later. Yes, I already did something similar - I developed a custom form class that inherits from form.Form and sets ignoreContext=True. The problem is how to setup widgets with their default values. In form.widget, there seem to be the following possibilities: 1) From request (Not applicable here) 2) From the data manger (As I tried) 3) From the default field value (Not possible here, as the value is not static) 4) Via an adapter providing IValue (Possible, but very complicated) So, only (3) seems to be the way to go, which confronts me with the above problems. > Or even better you can define a custom ISession object > which provides what you need. e.g. with useful default > values from the schema field definition. Such a custom > session object can be used within the EditForm and > you don't have to use the AddForm concept. > > > Such a search session object could look like: > > class ISearchSession(ISession): > """Message filter session.""" > > searchText = zope.schema.TextLine( > title=Search text', > description=u'The search text', > default=u'', > required=False) > > class SearchSessioon(Session): > _spd = None > > @Lazy > def spd(self): > return self.__getitem__('SEARCH_SESSION_KEY') > > @apply > def searchText(): > def get(self): > return self.spd.get('searchText', u'') > def set(self, searchText): > self.spd['searchText'] = searchText > return property(get, set) Is the parent object Session/ISession the one from zope.session? How does it connect to the persistent Session object? And what is "@Lazy"? Yes, that's a possibility, but it would force me to write: - An property for every field. - A class for every search view. All in all that's around ~ 200 lines of code for 5 search forms with appr. 5 fields each, compared to appr. 10 lines of code in my solution. > I allways use such a session implementation because it > abstracts what you need, uses schema fields, offers > built in defaults and works well with z3c.form. Yes, thanks for the code snippet, it's interesting and a clean solution. > Note; I'm still not 100% sure if the get() or query() > usage in applyChanges is right or wrong. I hope to > find time to deep into that in the near future. > > But I think nobody will understand the concept if we > implement a form property for use get or query in > applyChanges. Yes, that may be true. Hmmm... > Hope the session concept works for you till someone > agrees/checks the get/query useage. Well, I have two more possibilities until this is sorted out entirely: 1) Monkey patch z3c.form.DictionaryField.get() and let it return interfaces.NOVALUE 2) Write an register my own data manager to overcome this. Thanks again for help, Best Regards, Hermann -- [EMAIL PROTECTED] GPG key ID: 299893C7 (on keyservers) FP: 0124 2584 8809 EF2A DBF9 4902 64B4 D16B 2998 93C7 ___ Zope3-users mailing list Zope3-users@zope.org http://mail.zope.org/mailman/listinfo/zope3-users
Re: [Zope3-Users] z3c.form: Data Manager - getting value via dm.query() instead of dm.get()
Hi Hermann > Betreff: Re: AW: AW: [Zope3-Users] z3c.form: Data Manager - > getting value via dm.query() instead of dm.get() > > > > Hi Herman > > > >> Betreff: Re: AW: [Zope3-Users] z3c.form: Data Manager - > getting value > >> via dm.query() instead of dm.get() > > > > [...] > > > >> But I would nevertheless suggest to implement some kind of > "switch" > >> that decides if an error is raised or NOVALUE is returned > in case a > >> value is missing in the underlying object. > > > > I don't understand that. > > > > Why whould you like to store a default value if a value is missing. > > That's just a write access for storing what default returns anyway. > > Hmmm, perhaps I have to explain my case better: > > Normally, z3c.forms are used to edit/display content objects, > which is e.g. a "person object" with attributes such as > "name, etc.", which are then mapped to fields/widgets. In > case the underlying data object is a dictionary, this > dictionary has to provide all key/value pairs as specified in > the field.fields(). > > In my case, I'm creating a search form. This search form does > not store any data into a content object, it just calls a > specific search function. > However, the values in the search form should be remembered, > so that if the user comes back to the form, it is already > prefilled. Therefore, I simply store the "data" dictionary of > the button handler into the session and (mis)use this object > as content object: > > def getContent(): > return session.get('searchformkey', {}) > > def handle_search(self, action): > data, errors = self.extractData() > if errors: > self.searched = None > self.status = self.formErrorsMessage > return > self.do_search(data) > self.session['searchformkey'] = data > > So, it may happen, that not all fields are filled out, > therefore key/value pairs may be missing. If that happens, > the widget routine throws an error. > If I manage to overcome this error (e.g. by replacing the > get() through > query() routine in z3c.form.widget), my form works. > > Maybe, there's a better way to accomplish the above, but I > could not think of one... I understand. Ther must be something wrong. Take a look at the AddForm implementation this one uses ignoreContext = True. This forces to not store the values to the object. Because it doesn't use applyChanges like the EditForm does. For a SearchForm, you can use extractData offered from the form and do what every you need to do with the extracted form values. e.g. store them into a session. You can setup the widgets with this values later. Or even better you can define a custom ISession object which provides what you need. e.g. with useful default values from the schema field definition. Such a custom session object can be used within the EditForm and you don't have to use the AddForm concept. Such a search session object could look like: class ISearchSession(ISession): """Message filter session.""" searchText = zope.schema.TextLine( title=Search text', description=u'The search text', default=u'', required=False) class SearchSessioon(Session): _spd = None @Lazy def spd(self): return self.__getitem__('SEARCH_SESSION_KEY') @apply def searchText(): def get(self): return self.spd.get('searchText', u'') def set(self, searchText): self.spd['searchText'] = searchText return property(get, set) I allways use such a session implementation because it abstracts what you need, uses schema fields, offers built in defaults and works well with z3c.form. Note; I'm still not 100% sure if the get() or query() usage in applyChanges is right or wrong. I hope to find time to deep into that in the near future. But I think nobody will understand the concept if we implement a form property for use get or query in applyChanges. Hope the session concept works for you till someone agrees/checks the get/query useage. Regards Roger Ineichen > Best Regards, > Hermann > > -- > [EMAIL PROTECTED] > GPG key ID: 299893C7 (on keyservers) > FP: 0124 2584 8809 EF2A DBF9 4902 64B4 D16B 2998 93C7 > > > ___ Zope3-users mailing list Zope3-users@zope.org http://mail.zope.org/mailman/listinfo/zope3-users
Re: [Zope3-Users] z3c.form: Data Manager - getting value via dm.query() instead of dm.get()
> Hi Herman > >> Betreff: Re: AW: [Zope3-Users] z3c.form: Data Manager - >> getting value via dm.query() instead of dm.get() > > [...] > >> But I would nevertheless suggest to implement some kind of >> "switch" that decides if an error is raised or NOVALUE is >> returned in case a value is missing in the underlying object. > > I don't understand that. > > Why whould you like to store a default value if a value > is missing. That's just a write access for storing > what default returns anyway. Hmmm, perhaps I have to explain my case better: Normally, z3c.forms are used to edit/display content objects, which is e.g. a "person object" with attributes such as "name, etc.", which are then mapped to fields/widgets. In case the underlying data object is a dictionary, this dictionary has to provide all key/value pairs as specified in the field.fields(). In my case, I'm creating a search form. This search form does not store any data into a content object, it just calls a specific search function. However, the values in the search form should be remembered, so that if the user comes back to the form, it is already prefilled. Therefore, I simply store the "data" dictionary of the button handler into the session and (mis)use this object as content object: def getContent(): return session.get('searchformkey', {}) def handle_search(self, action): data, errors = self.extractData() if errors: self.searched = None self.status = self.formErrorsMessage return self.do_search(data) self.session['searchformkey'] = data So, it may happen, that not all fields are filled out, therefore key/value pairs may be missing. If that happens, the widget routine throws an error. If I manage to overcome this error (e.g. by replacing the get() through query() routine in z3c.form.widget), my form works. Maybe, there's a better way to accomplish the above, but I could not think of one... Best Regards, Hermann -- [EMAIL PROTECTED] GPG key ID: 299893C7 (on keyservers) FP: 0124 2584 8809 EF2A DBF9 4902 64B4 D16B 2998 93C7 ___ Zope3-users mailing list Zope3-users@zope.org http://mail.zope.org/mailman/listinfo/zope3-users
Re: [Zope3-Users] z3c.form: Data Manager - getting value via dm.query() instead of dm.get()
Hi Herman > Betreff: Re: AW: [Zope3-Users] z3c.form: Data Manager - > getting value via dm.query() instead of dm.get() [...] > But I would nevertheless suggest to implement some kind of > "switch" that decides if an error is raised or NOVALUE is > returned in case a value is missing in the underlying object. I don't understand that. Why whould you like to store a default value if a value is missing. That's just a write access for storing what default returns anyway. Regards Roger Ineichen > Many thanks for help! > > Best Regards, > Hermann > > -- > [EMAIL PROTECTED] > GPG key ID: 299893C7 (on keyservers) > FP: 0124 2584 8809 EF2A DBF9 4902 64B4 D16B 2998 93C7 > > > ___ Zope3-users mailing list Zope3-users@zope.org http://mail.zope.org/mailman/listinfo/zope3-users
Re: [Zope3-Users] z3c.form: Data Manager - getting value via dm.query() instead of dm.get()
> Hi Herman, Stephan > >> Betreff: [Zope3-Users] z3c.form: Data Manager - getting value >> via dm.query() instead of dm.get() >> >> Hi, >> I'm developing a z3c.form based form, which should store it's >> form values in the session. To accomplish that, the form >> needs to retrieve it's values from the session. >> >> My idea was to simply store the form data in the button >> handler method into the session as a dictionary. z3c.form >> then offers the "getContent()" >> method, which would simply retrieve the dictionary from the session. >> >> The problem is, that if the dictionary does not contain all >> fields, an error is raised. The reason for this error lies in >> line 97 in >> z3c.form.widget: The value is retrieved via the get() >> function (which does a dict.get()) and thus fails. >> >> The solution for this problem would be to replace the >> datamanager.get() by datamanager.query(), as this would >> return the default field value. > > No the datamanager doesn't know the default value. Or at least > the data manger is not responsible for that part. Hmmm, that makes sense, but in my use case I need a datamanger that returns "None / NOVALUE / whatever_that_indicates_that_there_is_no_value". > The data converter is responsible to return a default value. I see, so there would a possibility to let the datamanager return NOVALUE and let the data converter return None, I assume? > This means the data converter convert values from the form > and the (applyChanges) within the data manager stores them if > different. And only if they are different. In my case, I have a dictionary that may - not yet - provide the value. >> However, this may break other projects, therefore I would suggest to: >> >> - Introduce some form option such as "ContextQuery=True/False" >> - Either use dm.get() or .query() regarding to this option >> >> What's your opinion on this? Would this be a decent solution? > > This means it's important to setup any field in the data manager > and the values for them. There is no support for widget which > didn't get setup it's value correct. > But, > as far as I can see there is a problem with the interface. > the *query* method isn't declared in the IDataManager interface > at all and the *get* method provides a default value like: > > The ``get`` method is defined as: > def get(default=NOVALUE): > """Get the value. > > If no value can be found, return the default value. > """ Ah, I see - so that would denote, that the get() method would return NOVALUE as default? This would also solve my problem. But I would nevertheless suggest to implement some kind of "switch" that decides if an error is raised or NOVALUE is returned in case a value is missing in the underlying object. Many thanks for help! Best Regards, Hermann -- [EMAIL PROTECTED] GPG key ID: 299893C7 (on keyservers) FP: 0124 2584 8809 EF2A DBF9 4902 64B4 D16B 2998 93C7 ___ Zope3-users mailing list Zope3-users@zope.org http://mail.zope.org/mailman/listinfo/zope3-users
Re: [Zope3-Users] z3c.form: Data Manager - getting value via dm.query() instead of dm.get()
Hi Herman, Stephan > Betreff: [Zope3-Users] z3c.form: Data Manager - getting value > via dm.query() instead of dm.get() > > Hi, > I'm developing a z3c.form based form, which should store it's > form values in the session. To accomplish that, the form > needs to retrieve it's values from the session. > > My idea was to simply store the form data in the button > handler method into the session as a dictionary. z3c.form > then offers the "getContent()" > method, which would simply retrieve the dictionary from the session. > > The problem is, that if the dictionary does not contain all > fields, an error is raised. The reason for this error lies in > line 97 in > z3c.form.widget: The value is retrieved via the get() > function (which does a dict.get()) and thus fails. > > The solution for this problem would be to replace the > datamanager.get() by datamanager.query(), as this would > return the default field value. No the datamanager doesn't know the default value. Or at least the data manger is not responsible for that part. The interface.NOVALUE is a marker for *value not set yet*. This means that the value wasn't setup if you have NOVALUE. It has nothing to do with default value, None or missing value form a field. It's just a internal marker for *no value setup till now*. This NOVLAUE marker is responsible that a value get converted or not. The data converter is responsible to return a default value. This means the data converter convert values from the form and the (applyChanges) within the data manager stores them if different. And only if they are different. > However, this may break other projects, therefore I would suggest to: > > - Introduce some form option such as "ContextQuery=True/False" > - Either use dm.get() or .query() regarding to this option > > What's your opinion on this? Would this be a decent solution? This means it's important to setup any field in the data manager and the values for them. There is no support for widget which didn't get setup it's value correct. But, as far as I can see there is a problem with the interface. the *query* method isn't declared in the IDataManager interface at all and the *get* method provides a default value like: The ``get`` method is defined as: def get(default=NOVALUE): """Get the value. If no value can be found, return the default value. """ Stephan, Any hints about that? > Best Regards, > Hermann > > -- > [EMAIL PROTECTED] > GPG key ID: 299893C7 (on keyservers) > FP: 0124 2584 8809 EF2A DBF9 4902 64B4 D16B 2998 93C7 > > > ___ > Zope3-users mailing list > Zope3-users@zope.org > http://mail.zope.org/mailman/listinfo/zope3-users > ___ Zope3-users mailing list Zope3-users@zope.org http://mail.zope.org/mailman/listinfo/zope3-users
[Zope3-Users] z3c.form: Data Manager - getting value via dm.query() instead of dm.get()
Hi, I'm developing a z3c.form based form, which should store it's form values in the session. To accomplish that, the form needs to retrieve it's values from the session. My idea was to simply store the form data in the button handler method into the session as a dictionary. z3c.form then offers the "getContent()" method, which would simply retrieve the dictionary from the session. The problem is, that if the dictionary does not contain all fields, an error is raised. The reason for this error lies in line 97 in z3c.form.widget: The value is retrieved via the get() function (which does a dict.get()) and thus fails. The solution for this problem would be to replace the datamanager.get() by datamanager.query(), as this would return the default field value. However, this may break other projects, therefore I would suggest to: - Introduce some form option such as "ContextQuery=True/False" - Either use dm.get() or .query() regarding to this option What's your opinion on this? Would this be a decent solution? Best Regards, Hermann -- [EMAIL PROTECTED] GPG key ID: 299893C7 (on keyservers) FP: 0124 2584 8809 EF2A DBF9 4902 64B4 D16B 2998 93C7 ___ Zope3-users mailing list Zope3-users@zope.org http://mail.zope.org/mailman/listinfo/zope3-users