'str' object has no attribute 'year' with 2 or more datetime validators

1,023 views
Skip to first unread message

Daniel González

unread,
Apr 5, 2013, 7:23:39 AM4/5/13
to web...@googlegroups.com
Hi everyone,

I have noticed that i cannot use 2 or more datetime validators on the
same field.

I'm building a SCRUM project management app. Making the sprints module I
need to validate that a new sprint is inside the project date range, and
at the same time, the sprint doesn't overlaps with other sprints.
So I was using IS_DATETIME_IN_RANGE to check that the date is inside of
the project date range, and made a copy called IS_NOT_DATETIME_IN_RANGE
that I apply at execution time to check that the new sprint is not
inside the range of other sprints.

Trying to do this, I get this error:

File "applications/openmywork/modules/omw/core/model/tableinterface.py", line 118, in form
return SQLFORM(self.table, record=row_id, _id=form_id)
File "/home/demetrio/devel/web2py_2.3.2/gluon/sqlhtml.py", line 1036, in __init__
default = field.formatter(default)
File "/home/demetrio/devel/web2py_2.3.2/gluon/dal.py", line 8723, in formatter
value = item.formatter(value)
File "/home/demetrio/devel/web2py_2.3.2/gluon/validators.py", line 2243, in formatter
year = value.year
AttributeError: 'str' object has no attribute 'year'



It seems that the first time that a date validato is executed, it
formats to str, so in the second validator, it cannot recognice it.

Is there any way to make this validation using web2py validators at
execution time?

thanks in advance.
Daniel

Massimo Di Pierro

unread,
Apr 5, 2013, 5:30:30 PM4/5/13
to web...@googlegroups.com
I am very much interested in your project. Can you send some screenshots?

Anyway, the problem is that you are probably piping your validator to the normal one. Can I see your validator and how it is applied?

Daniel Gonzalez Zaballos

unread,
Apr 8, 2013, 5:20:34 AM4/8/13
to web...@googlegroups.com
Sorry for the delay in replying.

In the model declaration i have this:

###########################    Model    ######################################
                   Field('init_date', 'datetime', required=True,
                        default=datetime.datetime.now(), notnull=True, 
                        label=current.T('Init date'),
                        requires = [IS_DATETIME(format=current.T('%Y-%m-%d %H:%M:%S'),
                                               error_message='must be YYYY-MM-DD HH:MM:SS!')]),
                  
                   Field('end_date', 'datetime', required=True,
                        default=datetime.datetime.now(), notnull=True,
                        label=current.T('End date'),
                        requires = [IS_DATETIME(format=current.T('%Y-%m-%d %H:%M:%S'),
                                               error_message='must be YYYY-MM-DD HH:MM:SS!')]),
###########################   /Model    ######################################


And in the controller
###########################    Controller    ###################################
        requires = []
        
        requires += [IS_DATETIME_IN_RANGE( minimum = self.project.start_date,
                                           maximum = self.project.end_date,
                                           #format = current.T('%Y-%m-%d'),
                                           error_message = current.T("The date is out of the project date range %(min)s %(max)s") )]
        
        #get all sprints and set validation date out of other sprints 
        sprints = sprint.get_all()        
        for sp in sprints:
            #dont get the sprint if we are editing it
            if action == 'edit' and sp.id == self.project.id:
                pass
            else:
                requires += [IS_NOT_DATETIME_IN_RANGE(minimum = sp.init_date, 
                                                      maximum = sp.end_date,
                                                      format = current.T('%Y-%m-%d'),
                                                      error_message = current.T("The date overlaps with another sprint: %s" % sp.name)) ] 
                
        self.db.sprint.init_date.requires += requires
        self.db.sprint.end_date.requires += requires
###########################    /Controller    ###################################

The error is even without using the "IS_NOT_DATETIME_IN_RANGE". First it executes the IS_DATETIME formatter method and when it is going to execute the IS_DATETIME_IN_RANGE formatter, it breaks.

If I dont define in the model the "IS_DATETIME" it doesn't work too. I think that web2py uses the formatter method from the IS_DATETIME validator, only because is a datetime field, even if no one validator is defined in the requires parameter.

the IS_NOT_DATETIME_IN_RANGE is the same validator as IS_DATETIME_IN_RANGE, but with the operators changed.

########################## Validator #########################################
class IS_NOT_DATETIME_IN_RANGE(IS_DATETIME):
    """
    example::

        >>> v = IS_NOT_DATETIME_IN_RANGE(\
                minimum=datetime.datetime(2008,1,1,12,20), \
                maximum=datetime.datetime(2009,12,31,12,20), \
                format="%m/%d/%Y %H:%M",error_message="oops")
        >>> v('03/03/2008 12:40')
        (datetime.datetime(2008, 3, 3, 12, 40), None)

        >>> v('03/03/2010 10:34')
        (datetime.datetime(2010, 3, 3, 10, 34), 'oops')

        >>> v(datetime.datetime(2008,3,3,0,0))
        (datetime.datetime(2008, 3, 3, 0, 0), None)

        >>> v(datetime.datetime(2010,3,3,0,0))
        (datetime.datetime(2010, 3, 3, 0, 0), 'oops')
    """
    def __init__(self,
                 minimum=None,
                 maximum=None,
                 format='%Y-%m-%d %H:%M:%S',
                 error_message=None):
        self.minimum = minimum
        self.maximum = maximum
        if error_message is None:
            if minimum is None:
                error_message = "enter date and time on or before %(max)s"
            elif maximum is None:
                error_message = "enter date and time on or after %(min)s"
            else:
                error_message = "enter date and time out of range %(min)s %(max)s"
        IS_DATETIME.__init__(self,
                             format=format,
                             error_message=error_message)
        self.extremes = dict(min=minimum, max=maximum)
        
    def __call__(self, value):
        (value, msg) = IS_DATETIME.__call__(self, value)
        if msg is not None:
            return (value, msg)
        if self.minimum and self.minimum < value:
            return (value, translate(self.error_message) % self.extremes)
        if self.maximum and value < self.maximum:
            return (value, translate(self.error_message) % self.extremes)
        return (value, None)
    
########################## /Validator #########################################

And about the screenshots, there are some screenshots of the project attatched to the mail. This is the openMyWork project, a collaborative workspace, that i had announced some time ago in this list. We are refactoring a lot of code (mostly in the core of the app, to be able of manage some "sub-applications" inside (like a document management sub-app, or in a future a social network or a e-learning sub-app) and introducing some new features, like a the document Management sub-app that i have commented or development metodologies like scrum. I cannot show a lot for now (mainly because of the refactorization... there is a lot of things that doesn't work at the moment :D).There is still too much work to do :)

Regards
Daniel.


2013/4/5 Massimo Di Pierro <massimo....@gmail.com>

--
 
---
You received this message because you are subscribed to the Google Groups "web2py-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to web2py+un...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

screenshot1.png
screenshot2.png
screenshot3.png
screenshot4.png
screenshot5.png
Reply all
Reply to author
Forward
0 new messages