elasticsales/flask-mongorest — pull request #23 by xogeny (2013-02-17 21:51:46+00:00)
Title: Adding ability to use URIs as references to in ReferenceFields

These commits address two issues.

The first is that, previously, resources in a
ReferenceField were represented by ObjectIds (case as strings) in the resource
representations. This violates the REST principle of uniform interface because
in representations the resources should be identified by a consistent URI. But the
previous behavior had them represented as ObjectIds (e.g., 512101ad1d41c8be69ea8546)
in representations but then as URIs (/user/512101ad1d41c8be69ea8546) when trying to
GET the resources.

Even once that was addressed, another dimension of this issue
is that when issuing PUT or POST requests, the resources need to be identified in
the representations that are included as data in those requests. So the framework then
needed the ability to convert the URI back into Documents internally (which turned out
to be the bulk of the work).

Along the way, a few other issues were uncovered and some utility functions were
introduced (e.g., having POST requests return a 201 status code and a Location header). All of the features involving using strict URIs to achieve uniform interface
require the `uri_prefix` class variable to be set in the specific `Resource` class AND
that any `Document` that reference that `Resource` in a `ReferenceField` must also
be sure to add the "field name"->`Resource` mapping to the `related_resources` field
in that Document. But if both of those steps are followed, it should completely enable
the use of URIs in the handling of these resources.

Also note that these changes are **100% backward compatible** since the original
scheme for representing resources in representations is used if no value is given
in a `Resource` class for the `uri_prefix` variable. Since that variable didn't previously
exist and its default value is `None`, this should be the case for all existing code.

It is worth noting that URIs for resources **do not** include a trailing slash. This
is be design and convention. However, somewhere in the Flask/werkzeug processing
a request for URL without a trailing slash is turned into a redirect response with
a status code of 301. I'm not sure where this is done and whether it is possible
when implementing a view in Flask to instruct the system whether your view
represents a single resource or a collection. So (for now?) any attempt to GET
a resource based on its true URI (no trailing slash) will trigger a redirection. This
isn't technically a problem because a "real" client would simply follow the redirect.
However, the test client doesn't follow redirects and people may be surprised in
their test cases that their requests are returning 301s instead of 20xs. A simple
solution (at least when doing testing?) is to set the `app.url_map.strict_slashes`
flag to `False`. This seems to cause werkzeug to avoid the redirect and simply
formulate a response as if the redirect had happened.