# HG changeset patch # User Florent Cayré # Date 1462374461 -7200 # Node ID 1694e6e9ff941ebb10279b8dd1827d4e541ff33e # Parent 19cacea03fdefa5aab90c34e8684e4147ebcee6d [forms] Fix edition of TZDatetime attributes Parse the submitted web form values into a timezone-aware datetime (by default, UTC) when such an attribute is edited. This is done using an automatically-selected (by `web.formfield.guess_field`) field named `TZDatetimeField`. Closes #12666598. diff -r 19cacea03fde -r 1694e6e9ff94 cubicweb/web/formfields.py --- a/cubicweb/web/formfields.py Mon May 02 17:14:43 2016 +0200 +++ b/cubicweb/web/formfields.py Wed May 04 17:07:41 2016 +0200 @@ -42,6 +42,7 @@ .. autoclass:: cubicweb.web.formfields.BooleanField() .. autoclass:: cubicweb.web.formfields.DateField() .. autoclass:: cubicweb.web.formfields.DateTimeField() +.. autoclass:: cubicweb.web.formfields.TZDatetimeField() .. autoclass:: cubicweb.web.formfields.TimeField() .. autoclass:: cubicweb.web.formfields.TimeIntervalField() @@ -65,6 +66,8 @@ from datetime import datetime, timedelta +import pytz + from six import PY2, text_type, string_types from logilab.mtconverter import xml_escape @@ -1015,6 +1018,18 @@ etype = 'Datetime' +class TZDatetimeField(DateTimeField): + """ Use this field to edit a timezone-aware datetime (`TZDatetime` yams + type). Note the posted values are interpreted as UTC, so you may need to + convert them client-side, using some javascript in the corresponding widget. + """ + + def _ensure_correctly_typed(self, form, value): + tz_naive = super(TZDatetimeField, self)._ensure_correctly_typed( + form, value) + return tz_naive.replace(tzinfo=pytz.utc) + + class TimeField(DateField): """Use this field to edit time (`Time` yams type). @@ -1267,7 +1282,7 @@ 'Date': DateField, 'Datetime': DateTimeField, - 'TZDatetime': DateTimeField, + 'TZDatetime': TZDatetimeField, 'Time': TimeField, 'TZTime': TimeField, 'Interval': TimeIntervalField, diff -r 19cacea03fde -r 1694e6e9ff94 cubicweb/web/test/data/schema.py --- a/cubicweb/web/test/data/schema.py Mon May 02 17:14:43 2016 +0200 +++ b/cubicweb/web/test/data/schema.py Wed May 04 17:07:41 2016 +0200 @@ -17,7 +17,7 @@ # with CubicWeb. If not, see . from yams.buildobjs import (EntityType, RelationDefinition, SubjectRelation, - String, Int, Datetime, Boolean, Float) + String, Int, Datetime, Boolean, Float, TZDatetime) from yams.constraints import IntervalBoundConstraint from cubicweb import _ @@ -58,6 +58,7 @@ tel = Int() fax = Int() datenaiss = Datetime() + tzdatenaiss = TZDatetime() test = Boolean() description = String() salary = Float() diff -r 19cacea03fde -r 1694e6e9ff94 cubicweb/web/test/unittest_form.py --- a/cubicweb/web/test/unittest_form.py Mon May 02 17:14:43 2016 +0200 +++ b/cubicweb/web/test/unittest_form.py Wed May 04 17:07:41 2016 +0200 @@ -17,6 +17,8 @@ # with CubicWeb. If not, see . import time +from datetime import datetime +import pytz from xml.etree.ElementTree import fromstring from lxml import html @@ -30,7 +32,8 @@ from cubicweb.devtools.testlib import CubicWebTC from cubicweb.web.formfields import (IntField, StringField, RichTextField, PasswordField, DateTimeField, - FileField, EditableFileField) + FileField, EditableFileField, + TZDatetimeField) from cubicweb.web.formwidgets import PasswordInput, Input, DateTimePicker from cubicweb.web.views.forms import EntityFieldsForm, FieldsForm from cubicweb.web.views.workflow import ChangeStateForm @@ -260,6 +263,31 @@

You can either submit a new file using the browse button above, or choose to remove already uploaded file by checking the "detach attached file" check-box, or edit file content online with the widget below.

''' % {'eid': file.eid}) + def _modified_tzdatenaiss(self, eid, datestr, timestr): + ctx = {'tzdatenaiss-subjectdate:%d' % eid: datestr, + 'tzdatenaiss-subjecttime:%d' % eid: timestr} + with self.admin_access.web_request(**ctx) as req: + form = EntityFieldsForm(req, None, entity=req.entity_from_eid(eid)) + field = TZDatetimeField(name='tzdatenaiss', eidparam=True, + role='subject') + form.append_field(field) + form.build_context({}) + return field.has_been_modified(form) + + def test_tzdatetimefield(self): + """ Comparison of the tz-aware database-stored value and the posted data + should not crash, and the posted data should be considered UTC """ + tzd = datetime.now(pytz.utc).replace(second=0, microsecond=0) + datestr, timestr = tzd.strftime('%Y/%m/%d %H:%M').split() + with self.admin_access.web_request() as req: + eid = req.create_entity('Personne', nom=u'Flo', tzdatenaiss=tzd).eid + req.cnx.commit() + + modified = self._modified_tzdatenaiss(eid, datestr, timestr) + self.assertFalse(modified) + + modified = self._modified_tzdatenaiss(eid, '2016/05/04', '15:07') + self.assertTrue(modified) def test_passwordfield(self): class PFForm(EntityFieldsForm): diff -r 19cacea03fde -r 1694e6e9ff94 cubicweb/web/test/unittest_magicsearch.py --- a/cubicweb/web/test/unittest_magicsearch.py Mon May 02 17:14:43 2016 +0200 +++ b/cubicweb/web/test/unittest_magicsearch.py Wed May 04 17:07:41 2016 +0200 @@ -293,6 +293,7 @@ 'Any X WHERE X is Personne, X test A', 'Any X WHERE X is Personne, X titre A', 'Any X WHERE X is Personne, X travaille A', + 'Any X WHERE X is Personne, X tzdatenaiss A', 'Any X WHERE X is Personne, X web A', ], self.suggestions('Any X WHERE X is Personne, X ')) @@ -300,6 +301,7 @@ 'Any X WHERE X is Personne, X test A', 'Any X WHERE X is Personne, X titre A', 'Any X WHERE X is Personne, X travaille A', + 'Any X WHERE X is Personne, X tzdatenaiss A', ], self.suggestions('Any X WHERE X is Personne, X t')) # try completion on selected @@ -307,6 +309,7 @@ 'Any X WHERE X is Personne, Y is Societe, X test A', 'Any X WHERE X is Personne, Y is Societe, X titre A', 'Any X WHERE X is Personne, Y is Societe, X travaille Y', + 'Any X WHERE X is Personne, Y is Societe, X tzdatenaiss A', ], self.suggestions('Any X WHERE X is Personne, Y is Societe, X t')) # invalid relation should not break diff -r 19cacea03fde -r 1694e6e9ff94 cubicweb/web/test/unittest_views_editforms.py --- a/cubicweb/web/test/unittest_views_editforms.py Mon May 02 17:14:43 2016 +0200 +++ b/cubicweb/web/test/unittest_views_editforms.py Wed May 04 17:07:41 2016 +0200 @@ -121,6 +121,7 @@ ('tel', 'subject'), ('fax', 'subject'), ('datenaiss', 'subject'), + ('tzdatenaiss', 'subject'), ('test', 'subject'), ('description', 'subject'), ('salary', 'subject'),