Re: [Zope3-Users] z3c.form: Data Manager - getting value via dm.query() instead of dm.get()

2008-08-20 Thread Stephan Richter
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()

2008-08-14 Thread Roger Ineichen
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()

2008-08-14 Thread Hermann Himmelbauer

> 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()

2008-08-14 Thread Roger Ineichen
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()

2008-08-14 Thread Hermann Himmelbauer

> 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()

2008-08-13 Thread Roger Ineichen
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()

2008-08-13 Thread Hermann Himmelbauer

> 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()

2008-08-13 Thread Roger Ineichen
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()

2008-08-13 Thread Hermann Himmelbauer
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