Open loechel opened 8 years ago
I do not understand your question. What do you mean with: "if you try to resolve field value in a browser view the defaultFactory is executed again"
What do you mean with resolve field value?
I am sorry if my english is not good enough to explain the issue.
the value of a default factory is never written to the persitence layer, so browser views recalculate the expected value from the default factory.
Example: User 1 has name foo which is provided to the form via a default factory. User 1 submit form, which is written into db
User 2 access a browser view of the data. As name was not written, the default factory recaluclates data, which if for the current user 2 bar.
so value should be foo for everybody, on every view. But it gets different values on every access.
The default value concept should work in z3c.form. What you are probably seeing could depend on the default attribute in zope.schema field. The z3c.schema field defines a missing_value and a default attribute. The z3c.form should be able to compare "field.default is not field.missing_value" and then use the default value if the given input is NO_VALUE. But this does not fit for dynamic values.
You can try to define a factory for the field.default aka defaultFactory. Something like:
def getRequest():
interaction = zope.security.management.getInteraction()
return interaction.participations[0]
def defaultUsernameFactory():
request = getRequest()
return request.annotations.get('username', '')
Then you can define a schema with a field like:
class IUser(zope.interface.Interface):
username= zope.schemaChoice(
title=u"Country"
defaultFactory=defaultUsernameFactory
)
Anf your form could look like:
class UserForm(Form):
fields = fieldFields(interfaces.IUser).select('username')
def update(self):
# setup username
self.request.annotations('username') = 'Fred'
super(UserForm, self).update()
Does this make sense?
Another consequence of this is when we try to use the current date as default value of a date field:
def current_date():
return datetime.date.today()
class IContent(model.Schema):
date = schema.Date(
title=_(u'Date'),
required=True,
defaultFactory=current_date,
)
If I create content on 12/10/2018 and then try to access the date field on 12/11/2018, the returned value will be 12/11/2018 (current date) and not 12/10/2018. That is, it calls the current_date method again.
@projekt01 your proposal of https://github.com/zopefoundation/z3c.form/issues/32#issuecomment-152394631 doesn't solve the problem of https://github.com/zopefoundation/z3c.form/issues/32#issuecomment-445899970. @loechel's proposal makes more sense.
https://github.com/zopefoundation/z3c.form/blob/master/src/z3c/form/form.py#L46 tries to apply Changes on data if the have Changed, If you use a defaultFactory on a zope.schema field the value did not change, but also did not get written. This results in a side effect that if you try to resolve field value in a browser view the defaultFactory is executed again, and could provide a different result to different users.
easy solution always write defaultFactory Fields: change
to