Recent IS_DATETIME formatter error

50 views
Skip to first unread message

Ali

unread,
Feb 23, 2026, 8:23:28 PM (8 days ago) Feb 23
to py4web
Hi, 

I have a Field of the following format:

Field('meeting_time', 'datetime',
              requires=(IS_NOT_EMPTY(), IS_EXPR(
                  lambda v: T('The meeting time cannot exceed one year from now') if
                  (v > get_years_ahead_string(1)) else None), IS_DATETIME()))

The Field used to work properly, but today I noticed that if the IS_EXPR() requirement fails, the subsequent IS_DATETIME() requirement returns an error, and the program stops. The expected behavior is that the UI simply displays the error message provided by IS_EXPR(). The exact error is copied below:

  File "/py4web/py4web/utils/form.py", line 95, in make
    _value=field.formatter("" if value is None else value),
  File "/py4web/venv/lib/python3.10/site-packages/pydal/objects.py", line 2449, in formatter
    value = item.formatter(value)
  File "/py4web/venv/lib/python3.10/site-packages/pydal/validators.py", line 3962, in formatter
    year = value.year
AttributeError: 'str' object has no attribute 'year'

As shown, the error is in the IS_DATETIME formatter. I noticed a commit was recently made to pydal titled "version 20260216.1, fixes formatter for numbers and dates". To err on the side of caution, I updated pydal. But the issue persists. I plan to create a minimal example and send it over. In the meantime, please let me know if you have any insights into what the cause could be.

Thank you!
- ali

Dave S

unread,
Feb 24, 2026, 5:48:49 AM (7 days ago) Feb 24
to py4web
On Monday, February 23, 2026 at 5:23:28 PM UTC-8 Ali wrote:
Hi, 

I have a Field of the following format:

Field('meeting_time', 'datetime',
              requires=(IS_NOT_EMPTY(), IS_EXPR(
                  lambda v: T('The meeting time cannot exceed one year from now') if
                  (v > get_years_ahead_string(1)) else None), IS_DATETIME()))


Which DB are you using?  Is it SQLite? 

Is the v in your lambda function the meeting time?  That makes it look like your lambda is comparing a datetime to a string.

The Field used to work properly, but today I noticed that if the IS_EXPR() requirement fails, the subsequent IS_DATETIME() requirement returns an error, and the program stops. The expected behavior is that the UI simply displays the error message provided by IS_EXPR(). The exact error is copied below:

  File "/py4web/py4web/utils/form.py", line 95, in make
    _value=field.formatter("" if value is None else value),
  File "/py4web/venv/lib/python3.10/site-packages/pydal/objects.py", line 2449, in formatter
    value = item.formatter(value)
  File "/py4web/venv/lib/python3.10/site-packages/pydal/validators.py", line 3962, in formatter
    year = value.year
AttributeError: 'str' object has no attribute 'year'

As shown, the error is in the IS_DATETIME formatter. I noticed a commit was recently made to pydal titled "version 20260216.1, fixes formatter for numbers and dates". To err on the side of caution, I updated pydal. But the issue persists. I plan to create a minimal example and send it over. In the meantime, please let me know if you have any insights into what the cause could be.

Thank you!
- ali

/dps
 

Ali

unread,
Feb 24, 2026, 7:42:37 PM (7 days ago) Feb 24
to py4web
Dave, 

Thank you for your input.

I have faced the issue with SQLite and AWS's RDS MySQL.

You are right, v is the meeting time. The datetime communicated over the network is of the type string. (An example is 2026-03-02T13:12:01 retrieved from request.POST). That is why I compared v with a stringified datatime. (And as I said before, everything was fine until recently.)

Here is a minimal example to reproduce the issue. Define:

db.define_table('test',
                Field('name'),
                Field('meeting_time', 'datetime', requires=(IS_EXPR(
                    lambda v: T('The meeting time cannot be set beyond 2026.') if
                    (v > "2026-12-31T23:59:59") else None), IS_DATETIME()))
                )

Try adding values to it using a simple endpoint coded as below:

@action('test', method=['GET', 'POST'])
@action.uses('generic.html', db, auth, notification_count_injector)
def test():
    test_form = Form(
        db.test, csrf_session=session, formstyle=FormStyleBulma)

    return dict(test_form=test_form)

When submitting the form, if you add a meeting time before 2026, everything works fine. However, if a value after 2026 is entered, the program stops with the error mentioned above. The expected behavior is simply for the UI to display the error message inside IS_EXPR.

Please do not hesitate to let me know if any additional information is needed.

Thank!
- ali

Dave S

unread,
Feb 24, 2026, 10:43:54 PM (7 days ago) Feb 24
to py4web
On Tuesday, February 24, 2026 at 4:42:37 PM UTC-8 Ali wrote:
Dave, 

Thank you for your input.

I have faced the issue with SQLite and AWS's RDS MySQL.


I asked because of the way some DBs (SQLite) represent dates, and that could have been a factor, but the other DB you've used should point to some other issue.

You are right, v is the meeting time. The datetime communicated over the network is of the type string. (An example is 2026-03-02T13:12:01 retrieved from request.POST). That is why I compared v with a stringified datatime. (And as I said before, everything was fine until recently.)


Should have been obvious to me ... validators work against vars, but I was a bit slow.
 
Here is a minimal example to reproduce the issue. Define:

db.define_table('test',
                Field('name'),
                Field('meeting_time', 'datetime', requires=(IS_EXPR(
                    lambda v: T('The meeting time cannot be set beyond 2026.') if
                    (v > "2026-12-31T23:59:59") else None), IS_DATETIME()))
                )

Try adding values to it using a simple endpoint coded as below:

@action('test', method=['GET', 'POST'])
@action.uses('generic.html', db, auth, notification_count_injector)
def test():
    test_form = Form(
        db.test, csrf_session=session, formstyle=FormStyleBulma)

    return dict(test_form=test_form)

When submitting the form, if you add a meeting time before 2026, everything works fine. However, if a value after 2026 is entered, the program stops with the error mentioned above. The expected behavior is simply for the UI to display the error message inside IS_EXPR.

Please do not hesitate to let me know if any additional information is needed.

Thank!
- ali


Thanks for following up.  I probably don't have any "more" insights, but this may help others to advise you.

/dps

Ali

unread,
Feb 26, 2026, 11:28:59 PM (5 days ago) Feb 26
to py4web
Thank you, Dave.

I wonder if anyone else has any insights to share? 

Thank you!
- ali

Alan Etkin

unread,
Mar 1, 2026, 8:15:54 AM (2 days ago) Mar 1
to py4web
With just a surface check I wonder if comparison could not be made between Python datetime objects instead of strings, to avoid the formatting issue.

Regards

Alan

Ali

unread,
Mar 1, 2026, 4:31:36 PM (2 days ago) Mar 1
to py4web
Thank you, Alan.

The approach with the string used to work perfectly fine until recently. The datatime objects are communicated as a string over the network. That is why I compared strings.

BTW, I noticed a small issue in the minimal code I'd shared above. The fixture notification_count_injector should not be there. I provide the example below again, just in case. It is pretty straightforward, I believe.

Define:

db.define_table('test',
                Field('name'),
                Field('meeting_time', 'datetime', requires=(IS_EXPR(
                    lambda v: T('The meeting time cannot be set beyond 2026.') if
                    (v > "2026-12-31T23:59:59") else None), IS_DATETIME()))
                )

Try adding values to it using a simple endpoint coded as below:

@action('test', method=['GET', 'POST'])
@action.uses('generic.html', db)
def test():
    test_form = Form(db.test, csrf_session=session, formstyle=FormStyleBulma)

    return dict(test_form=test_form)

When submitting the form, if you add a meeting time before 2026, everything works fine. However, if a value after 2026 is entered, the program stops with the error mentioned above. The expected behavior is simply for the UI to display the error message inside IS_EXPR.

Please do not hesitate to let me know if any additional information is needed. 

Thank you,
- ali

Massimo DiPierro

unread,
Mar 1, 2026, 4:33:44 PM (2 days ago) Mar 1
to Ali, py4web
I agree it should work. Will check asap why does not

--
You received this message because you are subscribed to the Google Groups "py4web" group.
To unsubscribe from this group and stop receiving emails from it, send an email to py4web+un...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/py4web/0d1e76b8-91fb-42a2-927e-b8521e0b4ee5n%40googlegroups.com.
Reply all
Reply to author
Forward
0 new messages