Re: [web2py] lost dropbox with IS_IN_DB multiple validators [CLOSED]

83 views
Skip to first unread message

Richard Vézina

unread,
Jun 22, 2011, 5:05:58 PM6/22/11
to web...@googlegroups.com
FINALLY!

Thank you Anthony...

Now works perfectly...

With this syntax :

db.ref_tregistry.fnaregistry_id.requires =\
    [IS_EMPTY_OR(IS_IN_DB(db,'table.field1')),
     ONLY_ONE_CAN_BE_FILLED([request.vars.field2],error_message='Select a volume or an folder')]

It was drive me nuts to rewrite the IS_IN_DB to include my ONLY_ONE_CAN_BE_FILLED() validator... I was thinking hmm... What will I have to do with all the other validator... ;-)

Regards

Richard



On Wed, Jun 22, 2011 at 4:38 PM, Anthony <abas...@gmail.com> wrote:
How about you just do this somewhere:
 
db.table.field1.widget=SQLFORM.widgets.options.widget
 
or
 
db.define_table('table', Field('field', requires=..., widget=SQLFORM.widgets.options.widget))
 
Does that bring the drop-down back to your field?
 
Anthony

On Wednesday, June 22, 2011 4:07:22 PM UTC-4, Richard wrote:
I try to hack a bit with IS_IN_DB to include a "ornull=" option that give this :

class IS_IN_DB_DEV_ORNULL():
    """
    example::

        INPUT(_type='text', _name='name',
              requires=IS_IN_DB(db, db.mytable.myfield, zero=''))

    used for reference fields, rendered as a dropbox
    """

    def __init__(
        self,
        dbset,
        field,
        label=None,
        error_message='value not in database',
        orderby=None,
        groupby=None,
        cache=None,
        multiple=False,
        zero='',
        sort=False,
        _and=None,
        ornull=None,
        null=None,
        ):
        from dal import Table
        if isinstance(field,Table): field = field._id

        if hasattr(dbset, 'define_table'):
            self.dbset = dbset()
        else:
            self.dbset = dbset
        self.field = field
        (ktable, kfield) = str(self.field).split('.')
        if not label:
            label = '%%(%s)s' % kfield
        if isinstance(label,str):
            if regex1.match(str(label)):
                label = '%%(%s)s' % str(label).split('.')[-1]
            ks = regex2.findall(label)
            if not kfield in ks:
                ks += [kfield]
            fields = ks
        else:
            ks = [kfield]
            fields = 'all'
        self.fields = fields
        self.label = label
        self.ktable = ktable
        self.kfield = kfield
        self.ks = ks
        self.error_message = error_message
        self.theset = None
        self.orderby = orderby
        self.groupby = groupby
        self.cache = cache
        self.multiple = multiple
        self.zero = zero
        self.sort = sort
        self._and = _and
        self.ornull = ornull
        self.null = null

    def set_self_id(self, id):
        if self._and:
            self._and.record_id = id

    def build_set(self):
        if self.fields == 'all':
            fields = [f for f in self.dbset.db[self.ktable]]
        else:
            fields = [self.dbset.db[self.ktable][k] for k in self.fields]
        if self.dbset.db._dbname != 'gae':
            orderby = self.orderby or reduce(lambda a,b:a|b,fields)
            groupby = self.groupby
            dd = dict(orderby=orderby, groupby=groupby, cache=self.cache)
            records = self.dbset.select(*fields, **dd)
        else:
            orderby = self.orderby or reduce(lambda a,b:a|b,(f for f in fields if not f.name=='id'))
            dd = dict(orderby=orderby, cache=self.cache)
            records = self.dbset.select(self.dbset.db[self.ktable].ALL, **dd)
        self.theset = [str(r[self.kfield]) for r in records]
        if isinstance(self.label,str):
            self.labels = [self.label % dict(r) for r in records]
        else:
            self.labels = [self.label(r) for r in records]

    def options(self):
        self.build_set()
        items = [(k, self.labels[i]) for (i, k) in enumerate(self.theset)]
        if self.sort:
            items.sort(options_sorter)
        if self.zero != None and not self.multiple:
            items.insert(0,('',self.zero))
        return items

    def __call__(self, value):
        unused_value, empty = is_empty(value)
        """if self.multiple:
            if isinstance(value,list):
                values=value
            elif value:
                values = [value]
            else:
                values = []
            if isinstance(self.multiple,(tuple,list)) and \
                    not self.multiple[0]<=len(values)<self.multiple[1]:
                return (values, translate(self.error_message))
            if not [x for x in values if not x in self.theset]:
                return (values, None)
        elif self.theset:
            if value in self.theset:
                if self._and:
                   return self._and(value)
                else:
                    return (value, None)"""
        if self.ornull:
            if self.multiple:
                if isinstance(value,list):
                    values=value
                elif value:
                    values = [value]
                else:
                    values = []
                if isinstance(self.multiple,(tuple,list)) and \
                        not self.multiple[0]<=len(values)<self.multiple[1]:
                    return (values, translate(self.error_message))
                if not [x for x in values if not x in self.theset]:
                    return (values, None)
            elif self.theset:
                if value in self.theset:
                    if self._and:
                        return self._and(value)
                    else:
                        return (value, None)
            if empty:
                return (self.null, None)
        else:
            (ktable, kfield) = str(self.field).split('.')
            field = self.dbset.db[ktable][kfield]
            if self.dbset(field == value).count():
                if self._and:
                    return self._and(value)
                else:
                    return (value, None)
        return (value, translate(self.error_message))


But I am still stock with the NULL in both field that goes trought the database overriding my ONLY_ONE_CAN_BE_FILLED() validator...

I also try to add a _and= option to my ONLY_ONE_CAN_BE_FILLED() validator, but remove the dropbox...

The only solution that I can see now is to merge IS_IN_DB with ONLY_ONE_CAN_BE_FILLED() that is not going to be really DRY...

If someone can see an other solution, I am really open to the idea...

Richard


On Wed, Jun 22, 2011 at 10:31 AM, Richard Vézina <ml.richa...@gmail.com> wrote:
Hello Anthony,

The "_and=" works perfectly and bring back the dropbox, but as you mention, not all the logic of the validator that I pass in the _and= option is working... The IS_EMPTY_OR is overriding the 

Here the proper syntax to get the dropbox :

db.table.field1.requires =\
    IS_EMPTY_OR(IS_IN_DB(db,'table.field1'),
        _and=ONLY_ONE_CAN_BE_FILLED([request.vars.field2],error_message='Select only one')))

I try to remove the IS_EMPTY_OR, but as expected the IS_IN_DB  prevent insertion of a null...

Don't know what the best option to make it works properly...

Adding option to IS_EMPTY_OR() to allow inter independency with my ONLY_ONE_CAN_BE_FILLED() or make a _and= option to my ONLY_ONE_CAN_BE_FILLED() to make it works with IS_IN_DB??

Richard

On Tue, Jun 21, 2011 at 9:11 PM, Richard Vézina <ml.richa...@gmail.com> wrote:
Great thanks Anthony, I will try that tomorrow first time and I will report back.

Richard


On Tue, Jun 21, 2011 at 5:35 PM, Anthony <abas...@gmail.com> wrote:
When you need to use additional validators with IS_IN_DB but still want the dropbox, you can add the additional validators to the IS_IN_DB validator via its '_and' argument -- see http://web2py.com/book/default/chapter/07#Database-Validators. However, I'm not sure if that works when IS_IN_DB is inside an IS_NULL_OR validator. (Actually, IS_NULL_OR has been deprecated in favor of IS_EMPTY_OR.)
 
Anthony

On Tuesday, June 21, 2011 5:16:12 PM UTC-4, Richard wrote:
Hello,

I would like to know if the problem I face coming from the validator that I write or is a IS_IN_DB behavior in case of multiple validators??

Here my validator :

class ONLY_ONE_CAN_BE_FILLED(object)
    """Class representing a validator requiring at least one non-empty field in a set. """ 
    def __init__(
        self, 
        others, 
        error_message='Enter a value in at least one field'
        ): 
        self.others = others 
        self.error_message = error_message 

    def __call__(self, value): 
        okay = (value, None) 
        error = (value, self.error_message) 
        values = [] 
        values.append(value) 
        values.extend(self.others) 
        empties = [] 
        for v in values: 
            unused_v, empty = is_empty(v) 
            empties.append(empty) 
        if empties.count(False) == 1:
            return okay
        else:
            return error


But when i use it like this I lost my dropbox for the FK field1 :

db.table.field1.requires =\
    [IS_NULL_OR(IS_IN_DB(db,'othertable.id','%(fieldrepresent)s',orderby=('fieldrepresent'))),
     ONLY_ONE_CAN_BE_FILLED([request.vars.field2],error_message='Select a volume or an folder')]

I remember I read something about IS_IN_DB and [IS_IN_DB]...

Can I have the dropbox and the multiple validators at the same time??

Thanks

Richard






Anthony

unread,
Jun 22, 2011, 5:40:35 PM6/22/11
to web...@googlegroups.com
Yes, you can always set your own widgets -- there are defaults, but you can change them. See http://web2py.com/book/default/chapter/07#Widgets.

Richard Vézina

unread,
Jun 22, 2011, 5:54:55 PM6/22/11
to web...@googlegroups.com
I forgot about widget... My working time is split in differents aspect related to my project so I am lost sometimes when I am back to web2py... And I have some difficulties to follow the rhythm of the novelties...

I appreciate your help a lot Anthony.

Richard
Reply all
Reply to author
Forward
0 new messages