My vision for web2py theming

185 views
Skip to first unread message

Leonel Câmara

unread,
Oct 15, 2015, 6:42:37 PM10/15/15
to web2py-developers
I had some free time so I decided to implement a proof of concept of the vision I have for web2py theming.

It has some terrible hacks and should never be used by anyone in production but I would like to know what you guys think as I believe it also has some good ideas and can help us establish a direction if we can do this in a cleaner/saner way.

https://github.com/leonelcamara/welcome_themeable

All you can do that's different from the regular welcome is that in default/index you can click on the theme name to change the theme. I did it just so it would be really easy to demo the functionality.

I think something like this could free us from the "why is web2py tied to bootstrap" problem newbies have.


Kiran Subbaraman

unread,
Oct 15, 2015, 10:43:30 PM10/15/15
to web2py-d...@googlegroups.com
Would like to see this - but encountered an error. Am probably missing some configuration?

I went ahead and downloaded the zip version of the code, and extracted into web2py applications.
http://127.0.0.1:8000/welcome_themeable/default/index
This displays the following error:
Traceback (most recent call last):
  File "d:\code\git\web2py\gluon\main.py", line 447, in wsgibase
    serve_controller(request, response, session)
  File "d:\code\git\web2py\gluon\main.py", line 186, in serve_controller
    run_models_in(environment)
  File "d:\code\git\web2py\gluon\compileapp.py", line 569, in run_models_in
    restricted(code, environment, layer=model)
  File "d:\code\git\web2py\gluon\restricted.py", line 227, in restricted
    exec ccode in environment
  File "d:/code/git/web2py/applications/welcome_themeable/models/db.py", line 37, in <module>
    response.formstyle = myconf.take('forms.formstyle')  # or 'bootstrap3_stacked' or 'bootstrap2' or other
  File "d:\code\git\web2py\gluon\contrib\appconfig.py", line 71, in take
    (part, '-->'.join(walking)))
BaseException: forms not in config []

________________________________________
Kiran Subbaraman
http://subbaraman.wordpress.com/about/
--
-- mail from:GoogleGroups "web2py-developers" mailing list
make speech: web2py-d...@googlegroups.com
unsubscribe: web2py-develop...@googlegroups.com
details : http://groups.google.com/group/web2py-developers
the project: http://code.google.com/p/web2py/
official : http://www.web2py.com/
---
You received this message because you are subscribed to the Google Groups "web2py-developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to web2py-develop...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Leonel Câmara

unread,
Oct 16, 2015, 4:23:22 AM10/16/15
to web2py-developers
My bad, it's fixed now Kiran.

Niphlod

unread,
Oct 16, 2015, 8:45:49 AM10/16/15
to web2py-developers
uhm. it seems a lot of machinery to digest for every request ... and I wouldn't follow the override way. This way, every requst gets injected the "default" web2py-way, then you exec run.py to override it.... 
I don't see anything that allows to set a different set of widgets, which is kinda the main deal: formstyle isn't enough, client-side is out of web2py-way and playing with formstyles is what got us to the point of being "cornersided" by the wonderful, but kinda outdated, current set of widgets.

Leonel Câmara

unread,
Oct 16, 2015, 9:01:06 AM10/16/15
to web2py-developers
I don't see anything that allows to set a different set of widgets, which is kinda the main deal

You can override widgets in the theme's run.py, you can do anything you want there really.

>  and I wouldn't follow the override way. This way, every requst gets injected the "default" web2py-way, then you exec run.py to override it.... 

Of course that doing it this way was really just a shortcut and it's not anywhere close to ideal, I just wanted a quick n' dirty way of showing the functionality I want working so if others agreed this kind of functionality is desirable we can start designing a sane and more efficient way to get it.  .

I do think I've done a reasonable job making layout.html and other views themeable as I think they would need to be if we want to have proper themes. Basically I would like web2py to support the kind of workflow where you buy/download a nice looking theme adjusted to your project needs (say an eshop theme, a portfolio theme, etc) and you just add the stuff you need, it would make many projects a lot cheaper by putting most of the design and scaffolding out of the way.

Anthony

unread,
Oct 16, 2015, 11:58:03 AM10/16/15
to web2py-developers
Seems like you still have to copy and edit a complete layout.html for each new theme. Maybe we could make it easier to build a custom layout by breaking up the current layout.html (we already do this to an extent by separating out web2py_ajax.html). We might start with a wrapper layout that includes just the head and mostly empty body tag (except for maybe a JS block at the bottom) -- even this wrapper could itself comprise several included templates (such as web2py_ajax.html) for better modularity. Then create an inner layout to fill in the body tag, again including separate templates for different pieces to make it easier to swap sections.

Anthony

Leonel Câmara

unread,
Oct 16, 2015, 2:06:45 PM10/16/15
to web2py-developers
That's how I did it in this experiment anthony, but you don't need to, in fact the way this is made theme views take precedence when a view in the application extends or includes another so you can have only the views you want in the theme. Given so, if we break layout.html into a bunch of html files for each block that are included in the original layout.html then it would be easy to replace just the blocks you want.

Niphlod

unread,
Oct 16, 2015, 2:25:14 PM10/16/15
to web2py-developers
All I'm saying is that when I proposed the same deal a year ago (or more, it was right around the time bs3 was out), I was shut down pretty easily. 
No matter what, I end up doing it on a daily basis. 
Goes without saying that I'm not leveraging any MENU, grid and smartgrid, and that I specify custom widgets in Field definition every time. 
Overriding is "functonally" what we should do, the fact is though that in web2py it hasn't the same shiny effects it has on every other framework: given the peculiar execution model, for the sake of overridability and themeability we're going to waste a considerable amount of CPU on something that could/should be run just when web2py starts (or when the first request comes down from an app).

Massimo DiPierro

unread,
Oct 16, 2015, 3:11:25 PM10/16/15
to web2py-d...@googlegroups.com
If I understand this is a matter of replacing the welcome app. We can have more than one welcome app.

I also think we need to move forward. Times are mature for something better than web2py. We only have to agree in which direction to move. And it does not have to be backward compatible but if we could recycle pydal, templates and validators, we can recycle a lot of the documentation and the code.

Personally I think we need to do a better decoupling of CSS from the frameworks, but more JS coupling.

We could use tornado which has a module reload option and it is pretty portable and abandon the custom importer. In retrospect it creates more problems than it solves.


Massimo






Leonel Câmara

unread,
Oct 16, 2015, 3:38:14 PM10/16/15
to web2py-developers
If I understand this is a matter of replacing the welcome app. We can have more than one welcome app.

Not exactly. This would allow the same application to have completely different layouts and appearance by just changing the theme.

 
 if we could recycle pydal, templates and validators

This is pretty much what I love about web2py. The main reasons I started using web2py instead of other fullstack frameworks, were the DAL because I hate ORMs with a passion and the DAL, being so similar to regular SQL, meant I hardly had to learn anything, and the templates being pure python which meant I didn't need to learn a templating language just for web2py.

Personally I think we need to do a better decoupling of CSS from the frameworks, but more JS coupling.

I think we need to avoid coupling altogether. Coupling was what brought us to this problem. If we do more JS coupling we will be tied to a particular JS framework (even if its our own) and have the same problem all over again. Coupling should be provided by plugins (which we could also make and maintain) it shouldn't be part of the base. We need to go full MVC avoiding monoliths like SQLFORM that do everything in the same place.

pbreit

unread,
Oct 18, 2015, 1:29:38 AM10/18/15
to web2py-developers
I'm curious what an Ember/Angular/React-like framework from the mind of Massimo would look like.

Massimo DiPierro

unread,
Oct 18, 2015, 1:31:17 AM10/18/15
to web2py-d...@googlegroups.com
I like ractive.js and I cannot think of anything better. vue.js is also very nice. It is a little tricky to get them to cooperate with jQuery and often they conflict with jQuery plugins but that is also a problem with the other ones you mentioned.

Michele Comitini

unread,
Oct 18, 2015, 11:30:43 AM10/18/15
to web2py-developers
Before starting with the "web2py-ng" do we have a list of thing that are blockers in web2py dev experience?
That would give some concrete ideas to work on.
Frontend framework binding is an issue to put on that list.


Niphlod

unread,
Oct 19, 2015, 5:27:09 AM10/19/15
to web2py-developers
IMHO the huge blocker in matter of customization is widgets and formstyles that are part of the app rather than part of the core.
If we want to come up with a new SQLFORM.quickform that doesn't do usual stuff (a-la-demo massimo presented with ractive.js) we can recommend that leaving "OLD" form manipulation as it is.
The "usual stuff" is basically the validate() that splats the form and runs validate() on the widget itself rather than on the record passed with request.post_vars.

Massimo DiPierro

unread,
Dec 4, 2015, 11:26:35 AM12/4/15
to web2py-d...@googlegroups.com
we need to make a decision about this.

we do have a 3 possible form logic:
1) the current logic. SQLFORM(…) returns a helper which can be manipulated but must know in advance about the style
2) the gluino logic: Form(….) returns an abstract object that can be optionally serialized. It must know the style before being serialized
3) the ractive/w3 logic: From(….) return an abstract object that serialized in JSON. The conversion JSON->HTML is done client side in ractive.

My guess is we could merge 2+3 and offer both options and perhaps even re-implement SQLFORM on top of that. Example:

form = Form(db.table).process()
if form.accepted: …
if form.errors: …
… form cannot be manipulated as before unless form = form.html(formtyle=request.formstyle)
{{=form.html(formtyle=‘bootstrap3’)}}

and for backward compatibility

def SQLFORM(*a,**b): return Form(*a,**b).html(formtyle=request.formstyle)    

I have lots of this done using new (better) helpers but this will require extensive testing. Shall we make this a Christmas project?

Richard Vézina

unread,
Dec 4, 2015, 1:37:31 PM12/4/15
to web2py-d...@googlegroups.com
YES!

Massimo DiPierro

unread,
Dec 4, 2015, 11:24:23 PM12/4/15
to web2py-d...@googlegroups.com
On Dec 4, 2015, at 10:26 AM, Massimo DiPierro <massimo....@gmail.com> wrote:

we need to make a decision about this.

we do have a 3 possible form logic:
1) the current logic. SQLFORM(…) returns a helper which can be manipulated but must know in advance about the style
2) the gluino logic: Form(….) returns an abstract object that can be optionally serialized. It must know the style before being serialized
3) the ractive/w3 logic: From(….) return an abstract object that serialized in JSON. The conversion JSON->HTML is done client side in ractive.

My guess is we could merge 2+3 and offer both options and perhaps even re-implement SQLFORM on top of that. Example:

form = Form(db.table).process()
if form.accepted: …
if form.errors: …
… form cannot be manipulated as before unless form = form.html(formtyle=request.formstyle)
{{=form.html(formtyle=‘bootstrap3’)}}

and for backward compatibility

def SQLFORM(*a,**b): return Form(*a,**b).html(formtyle=request.formstyle)    

I have lots of this done using new (better) helpers but this will require extensive testing. Shall we make this a Chr
On Oct 19, 2015, at 4:27 AM, Niphlod <nip...@gmail.com> wrote:

Leonel Câmara

unread,
Dec 5, 2015, 8:15:39 AM12/5/15
to web2py-developers
I agree, lets work on this. However I don't like this:

 Form(*a,**b).html(formtyle=request.formstyle)
What I don't like is that it has an html method. It doesn't even make sense to have one since formstyle will be the one actually doing it. We should really just completely separate rendering the form from its abstract representation.

A cleaner way for me would be, for instance, to have a FormRenderer class, instances of that class or its subclasses would take an abstract form in the constructor and then render it in some desired way when called.

To be clear, I definitely support the number 2 option as I think that will give us a lot of flexibility.


Anthony

unread,
Dec 5, 2015, 3:30:59 PM12/5/15
to web2py-developers
On Saturday, December 5, 2015 at 8:15:39 AM UTC-5, Leonel Câmara wrote:
I agree, lets work on this. However I don't like this:

 Form(*a,**b).html(formtyle=request.formstyle)
What I don't like is that it has an html method. It doesn't even make sense to have one since formstyle will be the one actually doing it. We should really just completely separate rendering the form from its abstract representation.

A cleaner way for me would be, for instance, to have a FormRenderer class, instances of that class or its subclasses would take an abstract form in the constructor and then render it in some desired way when called.

I think the idea is to avoid adding any new global API objects (of course, your FormRenderer class could be imported explicitly like Auth, etc., but then that simply adds complication, particularly since it will often happen in a view). Anyway, I don't quite follow why the .html method on the form class "doesn't make sense" due to the existence of formstyle, and yet having an entirely separate class does make sense.

As an aside, if we think forms may be rendered/serialized in formats other than HTML (e.g., JSON to be used by a JS framework such as Ractive or React), perhaps we could instead name the method something like .render or .serialize.

Anthony

Massimo DiPierro

unread,
Dec 5, 2015, 5:59:25 PM12/5/15
to web2py-d...@googlegroups.com

To be clear. The html method would not generate html but the same object as sqlhtnl does today so that people can manipulate the form programmatically as the do today.

Reply all
Reply to author
Forward
0 new messages