So, let's start saying that the same behaviour is presented with or without
on_define. It's not a matter on lazy tables and lazy validators, it's a
matter on providing the validator with the data it needs to validate the
record.
- default value commented
- enter nothing, press submit : error is given back (as long as the table
is not empty) "value not in database". Correct: Nodeid NULL is not on the
node table
- enter nodeid 1 --> hubid None (correct), nodeid 1 (correct).
Small hitch: even if you defined hubid as notnull, it is a reference, and
references can be null for databases like sqlite. not sure if we can patch
the dal to specify the not null costraint for foreign keys (open a ticket
if you prefer). That anyway would throw an exception in the db, when
instead you'd like to show an error message in the app.
The problem your line of work is that you want a validator to run without
including the thing you'd like to validate in the form (you set hubid as
not readable and not writable). Even including a IS_NOT_EMPTY() wouldn't
help much.
- uncomment the default
- enter nodeid 2, hubid 6, nodeid 2 (correct)
- enter again nodeid 2, a new record with hubid 6 and nodeid 2 . The deal
is the same as before, in some way.... you have a validator running on
request.vars.HubID that is not there when you submit the form, because is
not readable. Setting it readable but not writable doesn't fit the bill,
because obviously it's displayed but not sent with the form either.
IS_NOT_IN_DB(db(db.tie.hubID==request.vars.hubID),'tie.nodeID',error_message=T('combination
hub and node already in database'))
translates to - when a field HubID is not in request.vars (your case) -
"find if there is a nodeID in the tie table where HubID == None, if there
is one, raise the error".
In these trials on the second comma we entered one of those, so in that
case the error raises, but for the wrong reason: a hubID None has been
inserted because lacking of a default value.
in your app I guess that hubID==None are not there, so the validator
doesn't find any record of those and you can insert your "double" record
just fine.
In web2py there is no support for unique among 2 columns, so the "trick"
used in the validator is used.....but using request.vars.hubid requires
that the form includes request.vars.hubid !!
few tricks to solve:
- a custom onvalidation (of course). Doesn't get much to code over your
validator and works
- including HubID as a hidden field (if you're willing to have HubID
"published" on the source page, the normal user wouldn't see this) form =
SQLFORM(db.tie, hidden=dict(hubID=6)) sends a hidden field "hubID" with 6
as value --> it's in request.vars --> the validator fires
--