Howdy. Recently I was hit with several requests for "best web frameworks" and the need to create a barrage of new applications. Fed up with both answering "how do I setup XYZ" and recreating the wheel constantly for Flask work, I started cobbling together a Skelton project. https://github.com/sean-/flask-skeleton There are several goals with this skeleton: 1) To demonstrate Flask in action in a complete context, as opposed to the fragmented set of tools that comprise Flask (Flask being a collection of modules is great, btw! But it means you have to bootstrap constantly). 2) I also wanted to show off some best practices and combat the effects of the MySQL stupid juice (use of MySQL has led to some incredibly bad examples for how to do things that end up being adopted by organizations and developers as "the way"). 3) To stop development on the skeleton and shift the skeleton over to maintenance mode as libraries improve (i.e. I don't want to see it advance beyond being a good starting point, but I do want to collect and improve on various best practices as they come up). It's not complete (see the TODO for a list of remaining bits as well as a list of what's done), but it represents a functioning point from which to launch your development. Things that are demonstrated well enough (some better than others): Application: *) Modularized development (filesystem layout) *) Integration with other WSGI Middleware's *) Session management (secure cookie handling) *) Static assets management Database (PostgreSQL): *) ORM Layer and examples *) PostgreSQL schema *) Database ROLEs and permissions *) PostgreSQL pl functions ORM (SQLAlchemy): *) Use of PostgreSQL functions with SQLAlchemy AAA (Access, Authentication, Authorization): *) Registration *) Login (via pl functions) *) Logout Caching (memcached): *) Objects *) memoized functions *) Views Development: *) Debugging toolbar *) Application profiling Templating (Jinja2): *) Template layout *) Template filters It's a total of about 10 steps and takes about 5-10min to get setup (excluding compiling PostgreSQL) if you follow the instructions in the INSTALL file. If folks are interested in reviewing or contributing, please drop me a line on github (I couldn't find a digest option for flask@ so I may drop from the list at some point). I'd be especially interested in a non-fail stylesheet since I don't imagine I'll spend many cycles on the look and feel. :~] Cheers. -sc -- Sean Chittenden sean@chittenden.org
On 06/03/2011 03:23 PM, Sean Chittenden wrote: > Howdy. Recently I was hit with several requests for "best web frameworks" and the need to create a barrage of new applications. Fed up with both answering "how do I setup XYZ" and recreating the wheel constantly for Flask work, I started cobbling together a Skelton project. > > https://github.com/sean-/flask-skeleton Technically, F-S is very impressive. However, I do not believe that it is useful for anyone besides yourself. > There are several goals with this skeleton: > > 1) To demonstrate Flask in action in a complete context, as opposed to the fragmented set of tools that comprise Flask (Flask being a collection of modules is great, btw! But it means you have to bootstrap constantly). > > 2) I also wanted to show off some best practices and combat the effects of the MySQL stupid juice (use of MySQL has led to some incredibly bad examples for how to do things that end up being adopted by organizations and developers as "the way"). > > 3) To stop development on the skeleton and shift the skeleton over to maintenance mode as libraries improve (i.e. I don't want to see it advance beyond being a good starting point, but I do want to collect and improve on various best practices as they come up). > > > It's not complete (see the TODO for a list of remaining bits as well as a list of what's done), but it represents a functioning point from which to launch your development. > > Things that are demonstrated well enough (some better than others): > > Application: > *) Modularized development (filesystem layout) > *) Integration with other WSGI Middleware's > *) Session management (secure cookie handling) > *) Static assets management Your filesystem layout is very nonstandard. Also, I think that module-specific "static" and "templates" folders are going away in Flask 0.7 (well, they will be blueprint-specific then, but the idea still holds). Secure cookies for sessions is built into Flask, and my Flask-Login extension protects session cookies from being stolen if you are conscious of when the user needs to be authenticated. > Database (PostgreSQL): > *) ORM Layer and examples > *) PostgreSQL schema > *) Database ROLEs and permissions > *) PostgreSQL pl functions > > ORM (SQLAlchemy): > *) Use of PostgreSQL functions with SQLAlchemy Which absolutely kills portability. MySQL sucks, but Postgres isn't the only other database out there. During development, for example, I would rather use SQLite, since I would not have to muck about with permissions and I could just delete the file if I needed to start over. And even without that, sometimes there are situations where we have to use databases that aren't Postgres. > AAA (Access, Authentication, Authorization): > *) Registration > *) Login (via pl functions) > *) Logout Because programming your application logic straight into the freaking database is definitely the way to go. You twist the MVC paradigm even more than Rails. > Caching (memcached): > *) Objects > *) memoized functions > *) Views > > Development: > *) Debugging toolbar > *) Application profiling > > Templating (Jinja2): > *) Template layout > *) Template filters > > It's a total of about 10 steps and takes about 5-10min to get setup (excluding compiling PostgreSQL) if you follow the instructions in the INSTALL file. And your install instructions are either BSD specific or Mac specific (and if Mac-specific, rely on the nightmare that is MacPorts.) Despite the fact that most non-Mac Python developers use Linux and most servers use Linux. > If folks are interested in reviewing or contributing, please drop me a line on github (I couldn't find a digest option for flask@ so I may drop from the list at some point). I'd be especially interested in a non-fail stylesheet since I don't imagine I'll spend many cycles on the look and feel. :~] And so far, I have not even gotten to the quality of your code. You are using "dict.has_key(k)" instead of "k in dict". You are using relative freaking imports without the dots. Both of those are deprecated, and look horrible to boot. This is obviously a you-specific project, and while I do not doubt that you have put a lot of time and effort into it, it does not consist of the best practices for the general Flask-using population. In fact, your comment bashing MySQL is longer than most of the code I would actually consider using. > Cheers. -sc > > -- > Sean Chittenden > sean@chittenden.org > -- Regards, Matthew "LeafStorm" Frazier http://leafstorm.us/
>> Howdy. Recently I was hit with several requests for "best web frameworks" and the need to create a barrage of new applications. Fed up with both answering "how do I setup XYZ" and recreating the wheel constantly for Flask work, I started cobbling together a Skelton project. >> >> https://github.com/sean-/flask-skeleton > > Technically, F-S is very impressive. However, I do not believe that it > is useful for anyone besides yourself. Very possible, but the organization of a Flask website isn't confidential and hopefully it's useful to someone. >> Application: >> *) Modularized development (filesystem layout) >> *) Integration with other WSGI Middleware's >> *) Session management (secure cookie handling) >> *) Static assets management > > Your filesystem layout is very nonstandard. Also, I think that > module-specific "static" and "templates" folders are going away in Flask > 0.7 (well, they will be blueprint-specific then, but the idea still holds). Yeah, I'm not terribly keen on the handling of this. I want to find a consistent way of doing this, however, so I'm all ears. What I was thinking would be to have per-module static assets, so a URL like: > http://www.example.com/static/mod1/mod1_file.jpg Would map to the filesystem path: > skeleton/module/mod1/static And then provide a Flask-Script that consolidates the static assets out of mod1 in to a global path so that nginx can serve them: > /www/nginx/htdocs/static/mod1/mod1_file.jpg That way nginx only has to serve a static root of /www/nginx/htdocs > Secure cookies for sessions is built into Flask, and my Flask-Login > extension protects session cookies from being stolen if you are > conscious of when the user needs to be authenticated. It does use SecureCookie and am pretty sure I want to use Flask-Login, but I haven't finished/figured authorization out completely yet. >> Database (PostgreSQL): >> *) ORM Layer and examples >> *) PostgreSQL schema >> *) Database ROLEs and permissions >> *) PostgreSQL pl functions >> >> ORM (SQLAlchemy): >> *) Use of PostgreSQL functions with SQLAlchemy > > Which absolutely kills portability. MySQL sucks, but Postgres isn't the > only other database out there. During development, for example, I would > rather use SQLite, since I would not have to muck about with permissions > and I could just delete the file if I needed to start over. And even > without that, sometimes there are situations where we have to use > databases that aren't Postgres. *nods* And I get that, but after ~12yrs of doing web work, catering to portability concerns leads to inferior products. I use SQLite for iOS work, but when it comes to database backed web applications... there aren't easily embedable alternatives. My original Flask app actually had the schema defined via SQLAlchemy and it was unwieldly, to say the least. Not supporting other database platforms was a conscious choice and one that I stand behind knowing the pros and cons. >> If folks are interested in reviewing or contributing, please drop me a line on github (I couldn't find a digest option for flask@ so I may drop from the list at some point). I'd be especially interested in a non-fail stylesheet since I don't imagine I'll spend many cycles on the look and feel. :~] > > And so far, I have not even gotten to the quality of your code. You are > using "dict.has_key(k)" instead of "k in dict". You are using relative > freaking imports without the dots. Both of those are deprecated, and > look horrible to boot. I'll wear this one on my sleeve: I'm still grappling with python coding styles. My primary language is C/C++ so I'm sure there are pythonic gaffes all over the place. Thanks for the feedback, however, I'll clean that up. -sc -- Sean Chittenden sean@chittenden.org
First off, I would like to apologize for being so harsh on my initial reply. It was incredibly unprofessional of me, and I did so without understanding your reasoning for the design choices. On 06/04/2011 01:55 PM, Sean Chittenden wrote: >>> Howdy. Recently I was hit with several requests for "best web frameworks" and the need to create a barrage of new applications. Fed up with both answering "how do I setup XYZ" and recreating the wheel constantly for Flask work, I started cobbling together a Skelton project. >>> >>> https://github.com/sean-/flask-skeleton >> >> Technically, F-S is very impressive. However, I do not believe that it >> is useful for anyone besides yourself. > > Very possible, but the organization of a Flask website isn't confidential and hopefully it's useful to someone. By my statement I meant that it was very specific to the components you use, not that it was not particularly useful in general. >>> Application: >>> *) Modularized development (filesystem layout) >>> *) Integration with other WSGI Middleware's >>> *) Session management (secure cookie handling) >>> *) Static assets management >> >> Your filesystem layout is very nonstandard. Also, I think that >> module-specific "static" and "templates" folders are going away in Flask >> 0.7 (well, they will be blueprint-specific then, but the idea still holds). > > Yeah, I'm not terribly keen on the handling of this. I want to find a consistent way of doing this, however, so I'm all ears. What I was thinking would be to have per-module static assets, so a URL like: > >> http://www.example.com/static/mod1/mod1_file.jpg > > > Would map to the filesystem path: > >> skeleton/module/mod1/static > > > And then provide a Flask-Script that consolidates the static assets out of mod1 in to a global path so that nginx can serve them: > >> /www/nginx/htdocs/static/mod1/mod1_file.jpg > > > That way nginx only has to serve a static root of /www/nginx/htdocs Hmmm...I did something like this for Flask-Uploads, but that was for uploaded files and not for static files. Right now, the static files infrastructure is heavily built into the _PackageBoundObject system. Which has the advantage that you do not have a "startup cost" with serving the static files like you do with Django, but it also limits the performance of the static files. Perhaps you should file a ticket on Flask's Github page suggesting a setting for moving the static file location. >> Secure cookies for sessions is built into Flask, and my Flask-Login >> extension protects session cookies from being stolen if you are >> conscious of when the user needs to be authenticated. > > It does use SecureCookie and am pretty sure I want to use Flask-Login, but I haven't finished/figured authorization out completely yet. And to be fair, Flask-Login wasn't released until after your skeleton. >>> Database (PostgreSQL): >>> *) ORM Layer and examples >>> *) PostgreSQL schema >>> *) Database ROLEs and permissions >>> *) PostgreSQL pl functions >>> >>> ORM (SQLAlchemy): >>> *) Use of PostgreSQL functions with SQLAlchemy >> >> Which absolutely kills portability. MySQL sucks, but Postgres isn't the >> only other database out there. During development, for example, I would >> rather use SQLite, since I would not have to muck about with permissions >> and I could just delete the file if I needed to start over. And even >> without that, sometimes there are situations where we have to use >> databases that aren't Postgres. > > *nods* And I get that, but after ~12yrs of doing web work, catering to portability concerns leads to inferior products. I use SQLite for iOS work, but when it comes to database backed web applications... there aren't easily embedable alternatives. My original Flask app actually had the schema defined via SQLAlchemy and it was unwieldly, to say the least. Not supporting other database platforms was a conscious choice and one that I stand behind knowing the pros and cons. It's your decision. Generating a schema from the code trades raw power for flexibility and conciseness (and DRY-ness). I usually come down on the side of DRY, but as they say, "Practicality beats purity." >>> If folks are interested in reviewing or contributing, please drop me a line on github (I couldn't find a digest option for flask@ so I may drop from the list at some point). I'd be especially interested in a non-fail stylesheet since I don't imagine I'll spend many cycles on the look and feel. :~] >> >> And so far, I have not even gotten to the quality of your code. You are >> using "dict.has_key(k)" instead of "k in dict". You are using relative >> freaking imports without the dots. Both of those are deprecated, and >> look horrible to boot. > > I'll wear this one on my sleeve: I'm still grappling with python coding styles. My primary language is C/C++ so I'm sure there are pythonic gaffes all over the place. Thanks for the feedback, however, I'll clean that up. -sc Again, I apologize for the harshness of my reaction. I suffer horrible allergic reactions to unidiomatic code. For someone who is new to Python, you are actually doing quite well (unlike some of the people I have seen on Stack Overflow). (Though definitely fix up those relative imports. They can get very confusing.) > -- > Sean Chittenden > sean@chittenden.org > -- Regards, Matthew "LeafStorm" Frazier http://leafstorm.us/
On 04/06/11 16:07, Matthew Frazier wrote: >> Application: >> *) Modularized development (filesystem layout) >> *) Integration with other WSGI Middleware's >> *) Session management (secure cookie handling) >> *) Static assets management > > Your filesystem layout is very nonstandard. Also, I think that > module-specific "static" and "templates" folders are going away in Flask > 0.7 (well, they will be blueprint-specific then, but the idea still holds). Hello, I'm quite new to Flask (I used it for a single application) and while Flask itself is very straightforward (very pythonic in that) I spent quite a long time figuring out how better organize my code. Unfortunately all the examples provided in the documentation are for small application and there are none for the more structured approach described in http://flask.pocoo.org/docs/patterns/packages/ or for application factory functions as described in http://flask.pocoo.org/docs/patterns/appfactories/ (I'm quite unsure on which is the best way to register before and after request handlers in connection with application factories, for example). I know that having templates to copy is for lazy people that do not want to use their own brain to figure out things, but having a more detailed description (in the form of a little bit more detailed documentation, real projects, or discussions on this mailing list) would be much appreciated. From my side, I can show how I structured my application, collect your comments, review others work and try to come up with a few pages of documentation. PS: > And so far, I have not even gotten to the quality of your code. You are > using "dict.has_key(k)" instead of "k in dict". You are using relative > freaking imports without the dots. Both of those are deprecated, and > look horrible to boot. Your comments sound quite harsh. While I agree with most of them (but I have not spent enough time yet reading the code) I would try to phrase them differently and bring this project on the right side instead of bashing it. Having what is presented as a "Flask best practice" example out there, which is not endorsed by a consistent part of the Flask community is not going to help anyone. Thank you. Cheers, -- Daniele
Héllo, > > And so far, I have not even gotten to the quality of your code. You are > > using "dict.has_key(k)" instead of "k in dict". You are using relative > > freaking imports without the dots. Both of those are deprecated, and > > look horrible to boot. > > Your comments sound quite harsh. While I agree with most of them (but I > have not spent enough time yet reading the code) I would try to phrase > them differently and bring this project on the right side instead of > bashing it. +1 > Having what is presented as a "Flask best practice" example > out there, which is not endorsed by a consistent part of the Flask > community is not going to help anyone. I'm not sure I understand this. Cheers, Amirouche
Thank you very much for your work on this - it's extremely useful for me! On 3 June 2011 20:23, Sean Chittenden <sean@chittenden.org> wrote: > Howdy. Recently I was hit with several requests for "best web frameworks" > and the need to create a barrage of new applications. Fed up with both > answering "how do I setup XYZ" and recreating the wheel constantly for Flask > work, I started cobbling together a Skelton project. > > https://github.com/sean-/flask-skeleton > > There are several goals with this skeleton: > > 1) To demonstrate Flask in action in a complete context, as opposed to the > fragmented set of tools that comprise Flask (Flask being a collection of > modules is great, btw! But it means you have to bootstrap constantly). > > 2) I also wanted to show off some best practices and combat the effects of > the MySQL stupid juice (use of MySQL has led to some incredibly bad examples > for how to do things that end up being adopted by organizations and > developers as "the way"). > > 3) To stop development on the skeleton and shift the skeleton over to > maintenance mode as libraries improve (i.e. I don't want to see it advance > beyond being a good starting point, but I do want to collect and improve on > various best practices as they come up). > > > It's not complete (see the TODO for a list of remaining bits as well as a > list of what's done), but it represents a functioning point from which to > launch your development. > > Things that are demonstrated well enough (some better than others): > > Application: > *) Modularized development (filesystem layout) > *) Integration with other WSGI Middleware's > *) Session management (secure cookie handling) > *) Static assets management > > Database (PostgreSQL): > *) ORM Layer and examples > *) PostgreSQL schema > *) Database ROLEs and permissions > *) PostgreSQL pl functions > > ORM (SQLAlchemy): > *) Use of PostgreSQL functions with SQLAlchemy > > AAA (Access, Authentication, Authorization): > *) Registration > *) Login (via pl functions) > *) Logout > > Caching (memcached): > *) Objects > *) memoized functions > *) Views > > Development: > *) Debugging toolbar > *) Application profiling > > Templating (Jinja2): > *) Template layout > *) Template filters > > It's a total of about 10 steps and takes about 5-10min to get setup > (excluding compiling PostgreSQL) if you follow the instructions in the > INSTALL file. > > If folks are interested in reviewing or contributing, please drop me a line > on github (I couldn't find a digest option for flask@ so I may drop from > the list at some point). I'd be especially interested in a non-fail > stylesheet since I don't imagine I'll spend many cycles on the look and > feel. :~] > > Cheers. -sc > > -- > Sean Chittenden > sean@chittenden.org > >
On 06/04/2011 02:23 AM, Sean Chittenden wrote: > > 2) I also wanted to show off some best practices and combat the effects of the MySQL stupid juice (use of MySQL has led to some incredibly bad examples for how to do things that end up being adopted by organizations and developers as "the way"). Hi, Can you give more explanation about this? Thanks
>> 2) I also wanted to show off some best practices and combat the effects of the MySQL stupid juice (use of MySQL has led to some incredibly bad examples for how to do things that end up being adopted by organizations and developers as "the way"). > > Hi, > Can you give more explanation about this? How many people think it's normal or acceptable to do the following? SELECT * FROM "user" where username = 'myuser'; ? People do that because there was no alternative in MySQL. Version 5 it's possible but the mindset to do otherwise has been stamped out. This kind of conditioning of "acceptable interactions" is an epidemic. Use of PL functions, VIEWs and multiple roles with different permissions aren't in the vocabulary of most open source developers now. -sc
On Fri, Jun 3, 2011 at 5:01 PM, Sean Chittenden <sean@chittenden.org> wrote: > How many people think it's normal or acceptable to do the following? > > SELECT * FROM "user" where username = 'myuser'; > How is this much different from: tag = Tag.query.filter_by(name = form.tag.data.lower()).first() From your Flask-Skeleton code? And what does this have to do with MySQL? -Steve
>> How many people think it's normal or acceptable to do the following? >> >> SELECT * FROM "user" where username = 'myuser'; > > How is this much different from: > >> tag = Tag.query.filter_by(name = form.tag.data.lower()).first() > >> > From your Flask-Skeleton code? And what does this have to do with MySQL? [ Feel free to continue this off-list, it wasn't my intention to start this discussion ] In the example, Tag data is sufficiently anonymous, so who cares about a rogue 'SELECT *' or information leakage in that context? I access Tag data using native SQLAlchemy. Depending on the type of application, ~90% of what I do can be accessed that way. But, Tag data isn't confidential. At worst, it would be embarrassing to have a bug that leaked rows, but there's no real damage done. Low value information, limited to no database controls. Few people question giving a web process access to 100% of the data in a table. The web user is given SELECT access to a table, but there is no real way to LIMIT the number of rows in a given query performed by a web process. Why? Largely technological reasons (not exclusively, but IMHO the dominant reason). Rhetorical question: is there ever a good reason to give a web user access to 100% of the user data, emails, legal records, health care information, logistical information (scheduling, arrivals, etc), or other possibly sensitive data sources? For sensitive information, a process should be limited to just 1 row of data at a time and a user should not have SELECT access to a table. So, with no SELECT access, how do you access that data? PL functions (with the SECURITY DEFINER flag set). Here are a few examples: Login and Registration views: > https://github.com/sean-/flask-skeleton/blob/master/skeleton/modules/aaa/views.py#L49 > https://github.com/sean-/flask-skeleton/blob/master/skeleton/modules/aaa/views.py#L138 And on the database side: > https://github.com/sean-/flask-skeleton/blob/master/sql/funcs.sql.in#L12 And here are the permissions: > https://github.com/sean-/flask-skeleton/blob/master/sql/perms.sql Note that neither the web role or email role has access to the shadow schema. Here's another example if you need more than one row of data: > SELECT * FROM some_table_function(user_id); Under the hood, use full-blown SQL to do whatever, but after you're done figuring out what needs to happen in terms of queries, codify that interaction. Think of it like contract programming for databases and web development: not always necessary, but extremely important at other times. This technique is quite pervasive when you get in to database table auditing, etc., but like I said, you hardly ever see it in the open source world. Cheers. -sc -- Sean Chittenden sean@chittenden.org
> Under the hood, use full-blown SQL to do whatever, but after you're done
figuring out what needs to happen in terms of queries, codify that
interaction. Think of it like contract programming for databases and web
development: not always necessary, but extremely important at other times.
This technique is quite pervasive when you get in to database table
auditing, etc., but like I said, you hardly ever see it in the open source
world.
Now that, was an educational bit of reading. much appreciated.
Sounds like software bigotry. 2011/6/3 Sean Chittenden <sean@chittenden.org> > > >> 2) I also wanted to show off some best practices and combat the effects > of the MySQL stupid juice (use of MySQL has led to some incredibly bad > examples for how to do things that end up being adopted by organizations and > developers as "the way"). > > > > Hi, > > Can you give more explanation about this? > > How many people think it's normal or acceptable to do the following? > > SELECT * FROM "user" where username = 'myuser'; > > ? People do that because there was no alternative in MySQL. Version 5 it's > possible but the mindset to do otherwise has been stamped out. This kind of > conditioning of "acceptable interactions" is an epidemic. Use of PL > functions, VIEWs and multiple roles with different permissions aren't in the > vocabulary of most open source developers now. -sc >