diff --git a/docs/becomingbig.rst b/docs/becomingbig.rst index c3c4a0b6..02344720 100644 --- a/docs/becomingbig.rst +++ b/docs/becomingbig.rst @@ -8,11 +8,11 @@ designed for large scale applications and does not attempt to do so, but that does not mean you picked the wrong tool in the first place. Flask is powered by Werkzeug and Jinja2, two libraries that are in use at -a number of large websites out there and all Flask does is bringing those +a number of large websites out there and all Flask does is bring those two together. Being a microframework, Flask is literally a single file. What that means for large applications is that it's probably a good idea to take the code from Flask and put it into a new module within the -applications and expanding on that. +applications and expand on that. What Could Be Improved? ----------------------- @@ -20,12 +20,12 @@ What Could Be Improved? For instance it makes a lot of sense to change the way endpoints (the names of the functions / URL rules) are handled to also take the module name into account. Right now the function name is the URL name, but -imagine you have a large applications consisting of multiple components. +imagine you have a large application consisting of multiple components. In that case, it makes a lot of sense to use dotted names for the URL endpoints. -Here some suggestions how Flask can be modified to better accomodate large -scale applications: +Here are some suggestions for how Flask can be modified to better +accomodate large-scale applications: - implement dotted names for URL endpoints - get rid of the decorator function registering which causes a lot @@ -35,7 +35,7 @@ scale applications: better solution would be to have one module with all URLs in there and specifing the target functions explicitly or by name and importing them when needed. -- switch to explicit request object passing. This makes it more to type +- switch to explicit request object passing. This requires more typing (because you now have something to pass around) but it makes it a whole lot easier to debug hairy situations and to test the code. - integrate the `Babel`_ i18n package or `SQLAlchemy`_ directly into the @@ -44,14 +44,14 @@ scale applications: .. _Babel: http://babel.edgewall.org/ .. _SQLAlchemy: http://www.sqlalchemy.org/ -Why does not Flask do all that by Default? +Why does Flask not do all that by Default? ------------------------------------------ There is a huge difference between a small application that only has to handle a couple of requests per second and with an overall code complexity -of less than 4000 lines of code or something of larger scale. At one +of less than 4000 lines of code and something of larger scale. At some point it becomes important to integrate external systems, different storage backends and more. If Flask was designed with all these contingencies in mind, it would be a -much more complex framework and less easy to get started with. +much more complex framework and harder to get started with. diff --git a/docs/deploying/mod_wsgi.rst b/docs/deploying/mod_wsgi.rst index 4a2875f2..a7bbc114 100644 --- a/docs/deploying/mod_wsgi.rst +++ b/docs/deploying/mod_wsgi.rst @@ -11,8 +11,8 @@ Installing `mod_wsgi` If you don't have `mod_wsgi` installed yet you have to either install it using a package manager or compile it yourself. -The mod_wsgi `installation instructions`_ cover installation instructions for -source installations on UNIX systems. +The mod_wsgi `installation instructions`_ cover source installations on UNIX +systems. If you are using ubuntu / debian you can apt-get it and activate it as follows:: @@ -44,7 +44,7 @@ For most applications the following file should be sufficient:: If you don't have a factory function for application creation but a singleton instance you can directly import that one as `application`. -Store that file somewhere where you will find it again (eg: +Store that file somewhere that you will find it again (e.g.: `/var/www/yourapplication`) and make sure that `yourapplication` and all the libraries that are in use are on the python load path. If you don't want to install it system wide consider using a `virtual python`_ instance. diff --git a/docs/design.rst b/docs/design.rst index ae1fd8d0..c4fd32dd 100644 --- a/docs/design.rst +++ b/docs/design.rst @@ -2,7 +2,7 @@ Design Decisions in Flask ========================= If you are curious why Flask does certain things the way it does and not -different, this section is for you. This should give you an idea about +differently, this section is for you. This should give you an idea about some of the design decisions that may appear arbitrary and surprising at first, especially in direct comparison with other frameworks. @@ -44,10 +44,10 @@ something it can be very helpful to create a minimal application to test specific behavior. When the application object is deleted everything it allocated will be freed again. -Another thing that becomes possible with having an explicit object laying +Another thing that becomes possible when you have an explicit object laying around in your code is that you can subclass the base class (:class:`~flask.Flask`) to alter specific behaviour. This would not be -possible without hacks if the object was created ahead of time for you +possible without hacks if the object were created ahead of time for you based on a class that is not exposed to you. But there is another very important reason why Flask depends on an @@ -83,23 +83,23 @@ that limitation that Jinja2 is *always* configured will probably go away, the decision to bundle one template engine and use that will not. Template engines are like programming languages and each of those engines -has a certain understandment about how things work. On the surface they +has a certain understanding about how things work. On the surface they all work the same: you tell the engine to evaluate a template with a set of variables and take the return value as string. But that's about where similarities end. Jinja2 for example has an extensive filter system, a certain way to do template inheritance, support for reusable blocks (macros) that can be used from inside templates and -also from Python code, is using unicode for all operations, supports +also from Python code, uses unicode for all operations, supports iterative template rendering, configurable syntax and more. On the other hand an engine like Genshi is based on XML stream evaluation, template inheritance by taking the availability of XPath into account and more. Mako on the other hand treats templates similar to Python modules. -When it comes to bridge a template engine with an application or framework -there is more than just rendering templates. Flask uses Jinja2's -extensive autoescaping support for instance. Also it provides ways to -access macros from Jinja2 templates. +When it comes to connecting a template engine with an application or +framework there is more than just rendering templates. For instance, +Flask uses Jinja2's extensive autoescaping support. Also it provides +ways to access macros from Jinja2 templates. A template abstraction layer that would not take the unique features of the template engines away is a science on its own and a too large @@ -115,9 +115,9 @@ over to the Ruby side of web development there we have a protocol very similar to WSGI. Just that it's called Rack there, but besides that it looks very much like a WSGI rendition for Ruby. But nearly all applications in Ruby land do not work with Rack directly, but on top of a -lirbary with the same name. This Rack library has two equivalents in +library with the same name. This Rack library has two equivalents in Python: WebOb (formerly Paste) and Werkzeug. Paste is still around but -from my understanding it's sortof deprecated in favour of WebOb. The +from my understanding it's sort of deprecated in favour of WebOb. The development of WebOb and Werkzeug started side by side with similar ideas in mind: be a good implementation of WSGI for other applications to take advantage. diff --git a/docs/installation.rst b/docs/installation.rst index 74c5f5e4..f2f4905f 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -9,10 +9,10 @@ way and why there are multiple ways. Flask depends on two external libraries: `Werkzeug `_ and `Jinja2 `_. -The first on is responsible for interfacing WSGI the latter to render +The first one is responsible for interfacing WSGI the latter for rendering templates. Now you are maybe asking, what is WSGI? WSGI is a standard in Python that is basically responsible for ensuring that your application -is behaving in a specific way that you can run it on different +is behaving in a specific way so that you can run it on different environments (for example on a local development server, on an Apache2, on lighttpd, on Google's App Engine or whatever you have in mind). @@ -26,10 +26,10 @@ Virtualenv is what you want to use during development and in production if you have shell access. So first: what does virtualenv do? If you are like me and you like Python, chances are you want to use it for another project as well. Now the more projects you have, the more likely it is -that you will be working with different versions of Python itself or a -library involved. Because let's face it: quite often libraries break -backwards compatibility and it's unlikely that your application will -not have any dependencies, that just won't happen. So virtualenv for the +that you will be working with different versions of Python itself or at +least an individual library. Because let's face it: quite often libraries +break backwards compatibility and it's unlikely that your application will +not have any dependencies, that just won't happen. So virtualenv to the rescue! It basically makes it possible to have multiple side-by-side @@ -47,7 +47,7 @@ or even better:: $ sudo pip install virtualenv -Changes are you have virtualenv installed on your system then. Maybe it's +Chances are you have virtualenv installed on your system then. Maybe it's even in your package manager (on ubuntu try ``sudo apt-get install python-virtualenv``). @@ -152,7 +152,7 @@ Once you have done that it's important to add the `easy_install` command and other Python scripts to the path. To do that you have to add the Python installation's Script folder to the `PATH` variable. -To do that, click right on your "Computer" desktop icon and click +To do that, right-click on your "Computer" desktop icon and click "Properties". On Windows Vista and Windows 7 then click on "Advanced System settings", on Windows XP click on the "Advanced" tab instead. Then click on the "Environment variables" button and double click on the "Path" @@ -165,7 +165,7 @@ the following value:: ;C:\Python26\Scripts -Then you are done. To check if it worked, open the cmd and execute +Then you are done. To check that it worked, open the cmd and execute "easy_install". If you have UAC enabled it should prompt you for admin privileges. diff --git a/docs/patterns/packages.rst b/docs/patterns/packages.rst index d0b28932..5e14625b 100644 --- a/docs/patterns/packages.rst +++ b/docs/patterns/packages.rst @@ -48,12 +48,12 @@ What did we gain from this? Now we can restructure the application a bit into multiple modules. The only thing you have to remember is the following quick checklist: -1. the `Flask` application object creation have to be in the +1. the `Flask` application object creation has to be in the `__init__.py` file. That way each module can import it safely and the - `__name__` variable will resole to the correct package. + `__name__` variable will resolve to the correct package. 2. all the view functions (the ones with a :meth:`~flask.Flask.route` decorator on top) have to be imported when in the `__init__.py` file. - Not the objects itself, but the module it is in. Do the importing at + Not the object itself, but the module it is in. Do the importing at the *bottom* of the file. Here an example `__init__.py`:: diff --git a/docs/patterns/sqlalchemy.rst b/docs/patterns/sqlalchemy.rst index 5a064469..32d41c08 100644 --- a/docs/patterns/sqlalchemy.rst +++ b/docs/patterns/sqlalchemy.rst @@ -6,7 +6,7 @@ SQLAlchemy in Flask Many people prefer `SQLAlchemy`_ for database access. In this case it's encouraged to use a package instead of a module for your flask application and drop the models into a separate module (:ref:`larger-applications`). -Although that is not necessary but makes a lot of sense. +While that is not necessary, it makes a lot of sense. There are three very common ways to use SQLAlchemy. I will outline each of them here: @@ -52,7 +52,7 @@ automatically remove database sessions at the end of the request for you:: db_session.remove() return response -Here an example model (put that into `models.py` for instance):: +Here is an example model (put this into `models.py`, e.g.):: from sqlalchemy import Column, Integer, String from yourapplication.database import Base @@ -70,7 +70,7 @@ Here an example model (put that into `models.py` for instance):: def __repr__(self): return '' % (self.name, self.email) -You can insert entries into the database like this then: +You can insert entries into the database like this: >>> from yourapplication.database import db_session >>> from yourapplication.models import User @@ -95,11 +95,11 @@ Manual Object Relational Mapping Manual object relational mapping has a few upsides and a few downsides versus the declarative approach from above. The main difference is that you define tables and classes separately and map them together. It's more -flexible but a little more to type. In general it works similar to the +flexible but a little more to type. In general it works like the declarative approach, so make sure to also split up your application into multiple modules in a package. -Here the example `database.py` module for your application:: +Here is an example `database.py` module for your application:: from sqlalchemy import create_engine, MetaData from sqlalchemy.orm import scoped_session, sessionmaker @@ -112,7 +112,7 @@ Here the example `database.py` module for your application:: def init_db(): metadata.create_all(bind=engine) -As for the declarative approach you need to close down the session after +As for the declarative approach you need to close the session after each request. Put this into your application module:: from yourapplication.database import db_session @@ -122,7 +122,7 @@ each request. Put this into your application module:: db_session.remove() return response -Here an example table and model (put that into `models.py` for instance):: +Here is an example table and model (put this into `models.py`):: from sqlalchemy import Table, Column, Integer, String from sqlalchemy.orm import mapper @@ -172,7 +172,7 @@ connection first so that we can use a transaction: SQLAlchemy will automatically commit for us. -To query your database, yu use the engine directly or use a connection: +To query your database, you use the engine directly or use a connection: >>> users.select(users.c.id == 1).execute().first() (1, u'admin', u'admin@localhost') @@ -183,7 +183,7 @@ These results are also dict-like tuples: >>> r['name'] u'admin' -You can also pass string of SQL statements to the +You can also pass strings of SQL statements to the :meth:`~sqlalchemy.engine.base.Connection.execute` method: >>> engine.execute('select * from users where id = :1', [1]).first() diff --git a/docs/patterns/sqlite3.rst b/docs/patterns/sqlite3.rst index 3e758002..c11e837d 100644 --- a/docs/patterns/sqlite3.rst +++ b/docs/patterns/sqlite3.rst @@ -3,12 +3,12 @@ Using SQLite 3 with Flask ========================= -In Flask you can implement opening of dabase connections at the beginning +In Flask you can implement opening of database connections at the beginning of the request and closing at the end with the :meth:`~flask.Flask.before_request` and :meth:`~flask.Flask.after_request` decorators in combination with the special :class:`~flask.g` object. -So here a simple example how you can use SQLite 3 with Flask:: +So here a simple example of how you can use SQLite 3 with Flask:: import sqlite3 from flask import g @@ -70,7 +70,7 @@ Initial Schemas Relational databases need schemas, so applications often ship a `schema.sql` file that creates the database. It's a good idea to provide -a function that creates the database bases on that schema. This function +a function that creates the database based on that schema. This function can do that for you:: from contextlib import closing diff --git a/docs/testing.rst b/docs/testing.rst index 5439fbaf..3ea1e9ba 100644 --- a/docs/testing.rst +++ b/docs/testing.rst @@ -8,14 +8,14 @@ Testing Flask Applications Not sure where that is coming from, and it's not entirely correct, but also not that far from the truth. Untested applications make it hard to improve existing code and developers of untested applications tend to -become pretty paranoid. If an application however has automated tests you -can savely change things and you will instantly know if your change broke +become pretty paranoid. If an application however has automated tests, you +can safely change things and you will instantly know if your change broke something. Flask gives you a couple of ways to test applications. It mainly does that by exposing the Werkzeug test :class:`~werkzeug.Client` class to your code and handling the context locals for you. You can then use that with -your favourite testing solution. In this documentation we will us the +your favourite testing solution. In this documentation we will use the :mod:`unittest` package that comes preinstalled with each Python installation. @@ -50,13 +50,13 @@ In order to test that, we add a second module ( if __name__ == '__main__': unittest.main() -The code in the `setUp` function creates a new test client and initialize +The code in the `setUp` function creates a new test client and initializes a new database. That function is called before each individual test function. -What the test client does for us is giving us a simple interface to the +What the test client does is give us a simple interface to the application. We can trigger test requests to the application and the client will also keep track of cookies for us. -Because SQLite3 is filesystem based we can easily use the tempfile module +Because SQLite3 is filesystem-based we can easily use the tempfile module to create a temporary database and initialize it. Just make sure that you keep a reference to the :class:`~tempfile.NamedTemporaryFile` around (we store it as `self.db` because of that) so that the garbage collector does @@ -112,20 +112,20 @@ Run it again and you should see one passing test:: OK -Of course you can submit forms with the test client as well which we will +Of course you can submit forms with the test client as well, which we will use now to log our user in. Logging In and Out ------------------ The majority of the functionality of our application is only available for -the administration user. So we need a way to log our test client into the +the administration user. So we need a way to log our test client in to the application and out of it again. For that we fire some requests to the login and logout pages with the required form data (username and password). Because the login and logout pages redirect, we tell the client to `follow_redirects`. -Add the following two methods do your `FlaskrTestCase` class:: +Add the following two methods to your `FlaskrTestCase` class:: def login(self, username, password): return self.app.post('/login', data=dict( @@ -137,7 +137,7 @@ Add the following two methods do your `FlaskrTestCase` class:: return self.app.get('/logout', follow_redirects=True) Now we can easily test if logging in and out works and that it fails with -invalid credentials. Add this as new test to the class:: +invalid credentials. Add this new test to the class:: def test_login_logout(self): rv = self.login(flaskr.USERNAME, flaskr.PASSWORD) @@ -165,7 +165,7 @@ like this:: assert '<Hello>' in rv.data assert 'HTML allowed here' in rv.data -Here we also check that HTML is allowed in the text but not in the title +Here we check that HTML is allowed in the text but not in the title, which is the intended behavior. Running that should now give us three passing tests::