Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs updates to match new Werkzeug docs #154

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
48 changes: 26 additions & 22 deletions docs/api.rst
Expand Up @@ -46,19 +46,21 @@ Incoming Request Data

.. attribute:: form

A :class:`~werkzeug.MultiDict` with the parsed form data from `POST`
or `PUT` requests. Please keep in mind that file uploads will not
end up here, but instead in the :attr:`files` attribute.
A :class:`~werkzeug.datastructures.MultiDict` with the parsed form
data from `POST` or `PUT` requests. Please keep in mind that file
uploads will not end up here, but instead in the :attr:`files`
attribute.

.. attribute:: args

A :class:`~werkzeug.MultiDict` with the parsed contents of the query
string. (The part in the URL after the question mark).
A :class:`~werkzeug.datastructures.MultiDict` with the parsed
contents of the query string. (The part in the URL after the
question mark).

.. attribute:: values

A :class:`~werkzeug.CombinedMultiDict` with the contents of both
:attr:`form` and :attr:`args`.
A :class:`~werkzeug.datastructures.CombinedMultiDict` with the
contents of both :attr:`form` and :attr:`args`.

.. attribute:: cookies

Expand All @@ -79,12 +81,13 @@ Incoming Request Data

.. attribute:: files

A :class:`~werkzeug.MultiDict` with files uploaded as part of a
`POST` or `PUT` request. Each file is stored as
:class:`~werkzeug.FileStorage` object. It basically behaves like a
standard file object you know from Python, with the difference that
it also has a :meth:`~werkzeug.FileStorage.save` function that can
store the file on the filesystem.
A :class:`~werkzeug.datastructures.MultiDict` with files
uploaded as part of a `POST` or `PUT` request. Each file
is stored as :class:`~werkzeug.datastructures.FileStorage`
object. It basically behaves like a standard file object
you know from Python, with the difference that it also has a
:meth:`~werkzeug.datastructures.FileStorage.save` function that
can store the file on the filesystem.

.. attribute:: environ

Expand Down Expand Up @@ -308,10 +311,10 @@ Useful Internals

.. data:: _request_ctx_stack

The internal :class:`~werkzeug.LocalStack` that is used to implement
all the context local objects used in Flask. This is a documented
instance and can be used by extensions and application code but the
use is discouraged in general.
The internal :class:`~werkzeug.local.LocalStack` that is used to
implement all the context local objects used in Flask. This is a
documented instance and can be used by extensions and application
code but the use is discouraged in general.

The following attributes are always present on each layer of the
stack:
Expand Down Expand Up @@ -356,9 +359,9 @@ Useful Internals
deferred cleanup functionality.

You might find this helpful for unittests where you need the
information from the context local around for a little longer. Make
sure to properly :meth:`~werkzeug.LocalStack.pop` the stack yourself in
that situation, otherwise your unittests will leak memory.
information from the context local around for a little longer.
Make sure to properly :meth:`~werkzeug.local.LocalStack.pop` the stack
yourself in that situation, otherwise your unittests will leak memory.

Signals
-------
Expand Down Expand Up @@ -434,8 +437,9 @@ exceptions where it is good to know that this object is an actual proxy:
- if the object reference is important (so for example for sending
:ref:`signals`)

If you need to get access to the underlying object that is proxied, you
can use the :meth:`~werkzeug.LocalProxy._get_current_object` method::
If you need to get access to the underlying object that is proxied,
you can use the :meth:`~werkzeug.local.LocalProxy._get_current_object`
method::

app = current_app._get_current_object()
my_signal.send(app)
2 changes: 1 addition & 1 deletion docs/conf.py
Expand Up @@ -243,7 +243,7 @@

intersphinx_mapping = {
'http://docs.python.org/dev': None,
'http://werkzeug.pocoo.org/documentation/dev/': None,
'http://werkzeug.pocoo.org/docs/': None,
'http://www.sqlalchemy.org/docs/': None,
'http://wtforms.simplecodes.com/docs/0.5/': None,
'http://discorporate.us/projects/Blinker/docs/1.1/': None
Expand Down
40 changes: 20 additions & 20 deletions docs/patterns/fileuploads.rst
Expand Up @@ -10,8 +10,8 @@ uploads is actually quite simple. It basically works like this:
and an ``<input type=file>`` is placed in that form.
2. The application accesses the file from the :attr:`~flask.request.files`
dictionary on the request object.
3. use the :meth:`~werkzeug.FileStorage.save` method of the file to save
the file permanently somewhere on the filesystem.
3. use the :meth:`~werkzeug.datastructures.FileStorage.save` method of
the file to save the file permanently somewhere on the filesystem.

A Gentle Introduction
---------------------
Expand All @@ -22,21 +22,21 @@ bootstrapping code for our application::

import os
from flask import Flask, request, redirect, url_for
from werkzeug import secure_filename
from werkzeug.utils import secure_filename

UPLOAD_FOLDER = '/path/to/the/uploads'
ALLOWED_EXTENSIONS = set(['txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif'])

app = Flask(__name__)

So first we need a couple of imports. Most should be straightforward, the
:func:`werkzeug.secure_filename` is explained a little bit later. The
`UPLOAD_FOLDER` is where we will store the uploaded files and the
`ALLOWED_EXTENSIONS` is the set of allowed file extensions. Then we add a
URL rule by hand to the application. Now usually we're not doing that, so
why here? The reasons is that we want the webserver (or our development
server) to serve these files for us and so we only need a rule to generate
the URL to these files.
So first we need a couple of imports. Most should be straightforward,
the :func:`werkzeug.utils.secure_filename` is explained a little bit
later. The `UPLOAD_FOLDER` is where we will store the uploaded files
and the `ALLOWED_EXTENSIONS` is the set of allowed file extensions.
Then we add a URL rule by hand to the application. Now usually we're
not doing that, so why here? The reasons is that we want the webserver
(or our development server) to serve these files for us and so we only
need a rule to generate the URL to these files.

Why do we limit the extensions that are allowed? You probably don't want
your users to be able to upload everything there if the server is directly
Expand Down Expand Up @@ -71,12 +71,12 @@ the file and redirects the user to the URL for the uploaded file::
</form>
'''

So what does that :func:`~werkzeug.secure_filename` function actually do?
Now the problem is that there is that principle called "never trust user
input". This is also true for the filename of an uploaded file. All
submitted form data can be forged, and filenames can be dangerous. For
the moment just remember: always use that function to secure a filename
before storing it directly on the filesystem.
So what does that :func:`~werkzeug.utils.secure_filename` function
actually do? Now the problem is that there is that principle called
"never trust user input". This is also true for the filename of an
uploaded file. All submitted form data can be forged, and filenames can
be dangerous. For the moment just remember: always use that function
to secure a filename before storing it directly on the filesystem.

.. admonition:: Information for the Pros

Expand Down Expand Up @@ -109,10 +109,10 @@ Flask 0.5 we can use a function that does that for us::
filename)

Alternatively you can register `uploaded_file` as `build_only` rule and
use the :class:`~werkzeug.SharedDataMiddleware`. This also works with
older versions of Flask::
use the :class:`~werkzeug.wsgi.SharedDataMiddleware`. This also works
with older versions of Flask::

from werkzeug import SharedDataMiddleware
from werkzeug.wsgi import SharedDataMiddleware
app.add_url_rule('/uploads/<filename>', 'uploaded_file',
build_only=True)
app.wsgi_app = SharedDataMiddleware(app.wsgi_app, {
Expand Down
12 changes: 6 additions & 6 deletions docs/patterns/jquery.rst
Expand Up @@ -108,12 +108,12 @@ template. This template will load jQuery as above and have a little form
we can add two numbers and a link to trigger the function on the server
side.

Note that we are using the :meth:`~werkzeug.MultiDict.get` method here
which will never fail. If the key is missing a default value (here ``0``)
is returned. Furthermore it can convert values to a specific type (like
in our case `int`). This is especially handy for code that is
triggered by a script (APIs, JavaScript etc.) because you don't need
special error reporting in that case.
Note that we are using the :meth:`~werkzeug.datastructures.MultiDict.get`
method here which will never fail. If the key is missing a default
value (here ``0``) is returned. Furthermore it can convert values to
a specific type (like in our case `int`). This is especially handy for
code that is triggered by a script (APIs, JavaScript etc.) because you
don't need special error reporting in that case.

The HTML
--------
Expand Down
2 changes: 1 addition & 1 deletion docs/patterns/lazyloading.rst
Expand Up @@ -58,7 +58,7 @@ loaded upfront. The trick to actually load the view function as needed.
This can be accomplished with a helper class that behaves just like a
function but internally imports the real function on first use::

from werkzeug import import_string, cached_property
from werkzeug.utils import import_string, cached_property

class LazyView(object):

Expand Down
32 changes: 16 additions & 16 deletions docs/quickstart.rst
Expand Up @@ -543,14 +543,14 @@ You can handle uploaded files with Flask easily. Just make sure not to
forget to set the ``enctype="multipart/form-data"`` attribute on your HTML
form, otherwise the browser will not transmit your files at all.

Uploaded files are stored in memory or at a temporary location on the
filesystem. You can access those files by looking at the
:attr:`~flask.request.files` attribute on the request object. Each
uploaded file is stored in that dictionary. It behaves just like a
standard Python :class:`file` object, but it also has a
:meth:`~werkzeug.FileStorage.save` method that allows you to store that
file on the filesystem of the server. Here is a simple example showing how
that works::
Uploaded files are stored in memory or at a temporary location
on the filesystem. You can access those files by looking at the
:attr:`~flask.request.files` attribute on the request object.
Each uploaded file is stored in that dictionary. It behaves just
like a standard Python :class:`file` object, but it also has a
:meth:`~werkzeug.datastructures.FileStorage.save` method that allows you
to store that file on the filesystem of the server. Here is a simple
example showing how that works::

from flask import request

Expand All @@ -561,16 +561,16 @@ that works::
f.save('/var/www/uploads/uploaded_file.txt')
...

If you want to know how the file was named on the client before it was
uploaded to your application, you can access the
:attr:`~werkzeug.FileStorage.filename` attribute. However please keep in
mind that this value can be forged so never ever trust that value. If you
want to use the filename of the client to store the file on the server,
pass it through the :func:`~werkzeug.secure_filename` function that
Werkzeug provides for you::
If you want to know how the file was named on the client
before it was uploaded to your application, you can access the
:attr:`~werkzeug.datastructures.FileStorage.filename` attribute. However
please keep in mind that this value can be forged so never ever trust that
value. If you want to use the filename of the client to store the file
on the server, pass it through the :func:`~werkzeug.utils.secure_filename`
function that Werkzeug provides for you::

from flask import request
from werkzeug import secure_filename
from werkzeug.utils import secure_filename

@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
Expand Down
24 changes: 12 additions & 12 deletions docs/testing.rst
Expand Up @@ -13,11 +13,11 @@ 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 use the
:mod:`unittest` package that comes preinstalled with each Python
installation.
that by exposing the Werkzeug test :class:`~werkzeug.test.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 use the :mod:`unittest` package that comes preinstalled with each
Python installation.

The Application
---------------
Expand Down Expand Up @@ -106,13 +106,13 @@ this::
rv = self.app.get('/')
assert 'No entries here so far' in rv.data

Test functions begin with the word `test`. Every function named like that
will be picked up automatically. By using `self.app.get` we can send an
HTTP `GET` request to the application with the given path. The return
value will be a :class:`~flask.Flask.response_class` object. We can now
use the :attr:`~werkzeug.BaseResponse.data` attribute to inspect the
return value (as string) from the application. In this case, we ensure
that ``'No entries here so far'`` is part of the output.
Test functions begin with the word `test`. Every function named like
that will be picked up automatically. By using `self.app.get` we can
send an HTTP `GET` request to the application with the given path.
The return value will be a :class:`~flask.Flask.response_class` object.
We can now use the :attr:`~werkzeug.wrappers.BaseResponse.data` attribute
to inspect the return value (as string) from the application. In this
case, we ensure that ``'No entries here so far'`` is part of the output.

Run it again and you should see one passing test::

Expand Down