experimental in trunk... common_fields and precints

171 views
Skip to first unread message

Massimo Di Pierro

unread,
May 25, 2011, 11:47:14 PM5/25/11
to web2py-users
There are two more features in trunk that I could use some testing
with (common fields and precints)

Imagine you have created an app "school" designed to manage one
school. It has one database and many tables. You wrote it with one
school in mind. Now you want to turn it into a service so that
multiple schools can register and use it. You want to identify the
school for example by the url http://harvard.anyschool.org and each
school should ONLY see its own users, groups, records, etc. etc.

Before today to do this you would have to rewrite all your tables and
queries.

Today you can do it without changing your code at all. You just have
to add this line after db=DAL(...)


db._common_fields=[Field('request_precinct',default=request.env.http_host,writable=False,readable=False)]

Yes. That is it!

How does it work?

1) db._common_fields is a list of fields that you want to add to all
tables.
2) The field called 'request_precinct' is special. Every query
involving a table having this field is automatically filtered byfield
value == field default. In our example the default is
request.env.http_host, i.e. the hostname in the http request which
identifies the school.
3) The field is hidden (writable=False,readable=False) but has a
default therefore it is automatically set for all inserts.

There is nothing special about schools here. You can use it with any
other app.

Give it a try and let me know.

I could use some help in writing some documentation about the new
features added today. ;-)

Massimo



mattgorecki

unread,
May 26, 2011, 12:37:28 AM5/26/11
to web2py-users
So in this example request_precinct would equal harvard.anyschool.org?

Matt

On May 25, 9:47 pm, Massimo Di Pierro <massimo.dipie...@gmail.com>
wrote:
> There are two more features in trunk that I could use some testing
> with (common fields and precints)
>
> Imagine you have created an app "school" designed to manage one
> school. It has one database and many tables. You wrote it with one
> school in mind. Now you want to turn it into a service so that
> multiple schools can register and use it. You want to identify the
> school for example by the urlhttp://harvard.anyschool.organd each

Massimo Di Pierro

unread,
May 26, 2011, 8:17:49 AM5/26/11
to web2py-users
yes.

Massimo Di Pierro

unread,
May 26, 2011, 10:10:55 AM5/26/11
to web2py-users
I changed 'request_precinct' to 'request_tenant' since this is more
appropriate. We are talking about buildig multi-tenant apps.

db._common_fields=[Field('request_tenant',default=request.env.http_host,w
ritable=False,readable=False)]

Notice you can also do

db._common_fields=[auth.signature]

and all tables will have created_by, modified_by, created_on,
modified_on, etc.


On May 26, 7:17 am, Massimo Di Pierro <massimo.dipie...@gmail.com>

Bruno Rocha

unread,
May 26, 2011, 10:18:10 AM5/26/11
to web...@googlegroups.com
On Thu, May 26, 2011 at 11:10 AM, Massimo Di Pierro <massimo....@gmail.com> wrote:
db._common_fields=[auth.signature]

and all tables will have created_by, modified_by, created_on,
modified_on, etc.

That is a very nice feature! I was implementing it from scratch creating an 'company_id' for every table, I am going to do some tests today 

Tom Atkins

unread,
May 26, 2011, 10:30:10 AM5/26/11
to web...@googlegroups.com
This is very useful - thanks Massimo! I will do some testing too...

Still working on the LMS? ;-)

Anthony

unread,
May 26, 2011, 10:31:48 AM5/26/11
to web...@googlegroups.com
On Thursday, May 26, 2011 10:10:55 AM UTC-4, Massimo Di Pierro wrote:
I changed 'request_precinct' to 'request_tenant' since this is more
appropriate. We are talking about buildig multi-tenant apps.
 
Does it have to be 'request_tenant', or is it possible to use a custom name, like 'company_id'?
 
Anthony

Massimo Di Pierro

unread,
May 26, 2011, 10:43:47 AM5/26/11
to web2py-users
db._request_tenant = 'company_id'

villas

unread,
May 26, 2011, 10:52:21 AM5/26/11
to web2py-users
Hi Massimo

My thought/suggestions are:

Almost everyone using this feature will also wish to keep data
relating to the tenant, e.g. they will have a 'tenant' table with
information about 'harvard.school.org'.

The foreign key relating to the 'tenant' table under your system would
therefore be using the string 'harvard.school.org' rather than an id
integer. Is that a good idea?

Many webservers will accept any sub-domain and this could lead to the
field 'request_tenant' being populated with misspellings etc,
e.g. 'harvd.school.org' or 'harverd.school.org',
'harvhard.school.org'. This would be difficult to relate to a
'tenant' table.

To stop those problems, you might still consider to use the ideas in
my original suggestion, i.e.
* lookup the sub-domain when the request is received and allocate an
id reference.
* specify what to do if the sub-domain is not recognised i.e. provide
a default value or raise an error (maybe 404).
* to save time when it is a single tenant system, set a global
constant to avoid the overhead of the multi-tenant lookup.

Regards,
David

On May 26, 3:10 pm, Massimo Di Pierro <massimo.dipie...@gmail.com>

Massimo Di Pierro

unread,
May 26, 2011, 11:30:38 AM5/26/11
to web2py-users
You can do what you ask

db.define_table('tenant',Field('name'))
# somehow store a tenant.id in session.tenant_id
# use tenant id for all other tables but the one above
db._common_fields=[Field('request_tenant',default=session.tenant_id,writable=False,readable=False)]

villas

unread,
May 26, 2011, 11:38:00 AM5/26/11
to web2py-users
Thanks, that sounds like a solution and I will experiment a little.
I like this feature very much!


On May 26, 4:30 pm, Massimo Di Pierro <massimo.dipie...@gmail.com>

Chris S

unread,
Jun 25, 2011, 8:08:06 PM6/25/11
to web2py-users
This is great, I've been away from web2py for about a year now and
this feature is exactly what I was trying to do quite some time ago by
manually storing and filtering by a SiteId.

A couple of questions.
1 - Is there a way to over ride the filter if you do not want it, for
say Administration?
2 - Can you define tables that are 'global' which always over ride the
feature? In this case I'm thinking a read-only table that all sites
retrieve information from.



On May 26, 10:38 am, villas <villa...@gmail.com> wrote:
> Thanks, that sounds like a solution and I will experiment a little.
> I like thisfeaturevery much!
>
> On May 26, 4:30 pm, Massimo Di Pierro <massimo.dipie...@gmail.com>
> wrote:
>
>
>
>
>
>
>
> > You can do what you ask
>
> > db.define_table('tenant',Field('name'))
> > # somehow store a tenant.id in session.tenant_id
> > # use tenant id for all other tables but the one above
> > db._common_fields=[Field('request_tenant',default=session.tenant_id,writabl e=False,readable=False)]
>
> > On May 26, 9:52 am, villas <villa...@gmail.com> wrote:
>
> > > Hi Massimo
>
> > > My thought/suggestions are:
>
> > > Almost everyone using thisfeaturewill also wish to keep data
> > > > > > > with (commonfieldsand precints)
>
> > > > > > > Imagine you have created an app "school" designed to manage one
> > > > > > > school. It has one database and many tables. You wrote it with one
> > > > > > > school in mind. Now you want to turn it into a service so that
> > > > > > > multiple schools can register and use it. You want to identify the
> > > > > > > school for example by the urlhttp://harvard.anyschool.organdeach
> > > > > > > school should ONLY see its own users, groups, records, etc. etc.
>
> > > > > > > Before today to do this you would have to rewrite all your tables and
> > > > > > > queries.
>
> > > > > > > Today you can do it without changing your code at all. You just have
> > > > > > > to add this line after db=DAL(...)
>
> > > > > > > db._common_fields=[Field('request_precinct',default=request.env.http_host,w ritable=False,readable=False)]
>
> > > > > > > Yes. That is it!
>
> > > > > > > How does it work?
>
> > > > > > > 1) db._common_fields is a list offieldsthat you want to add to all

Chris S

unread,
Jun 25, 2011, 8:10:01 PM6/25/11
to web2py-users
Ah there was one other scenario I meant to as.

Can you have an entry in the table which, when filtered, always
passes?
Here I'm thinking about a cross-site admin that could register a
single time and be retrieved from any of the accessing URL's.

On Jun 25, 7:08 pm, Chris S <sanders.ch...@gmail.com> wrote:
> This is great, I've been away from web2py for about a year now and
> thisfeatureis exactly what I was trying to do quite some time ago by
> manually storing and filtering by a SiteId.
>
> A couple of questions.
> 1 - Is there a way to over ride the filter if you do not want it, for
> say Administration?
> 2 - Can you define tables that are 'global' which always over ride thefeature?  In this case I'm thinking a read-only table that all sites

villas

unread,
Jun 26, 2011, 4:44:28 PM6/26/11
to web...@googlegroups.com
The tables defined with a request_tenant field have the multi-tenant feature.
If you want a 'global' table,  then define it before you start using the request_tenant field.

Chris S

unread,
Jun 26, 2011, 5:05:40 PM6/26/11
to web2py-users
So does that mean tables defined before:
db._common_fields=[Field('request_precinct',default=request.env.http_host,writable=False,readable=False)]

Don't get populated with the common field?
If so that's great, lets you define which tables get fields, or even
have several levels of "common fields".

Massimo Di Pierro

unread,
Jun 26, 2011, 5:09:28 PM6/26/11
to web2py-users
correct

Jason (spot) Brower

unread,
Jun 27, 2011, 12:35:47 AM6/27/11
to web...@googlegroups.com
I just found this thread.  This is an awesome feature I could see using a lot in the future.
BR,
Jason

Cliff

unread,
Jun 27, 2011, 4:02:48 PM6/27/11
to web2py-users
This is perfect timing. I, too, was beginning to implement an
organization_id feature in the app I'm porting from PHP.

Bravo!

Cliff
Reply all
Reply to author
Forward
0 new messages