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

Declarative url_for construction #77

Closed
jace opened this issue Dec 2, 2015 · 2 comments
Closed

Declarative url_for construction #77

jace opened this issue Dec 2, 2015 · 2 comments

Comments

@jace
Copy link
Member

jace commented Dec 2, 2015

coaster.sqlalchemy.UrlForMixin has made view construction much simpler by allowing for usage in the form of {{ ob.url_for() }} instead of the longer {{ url_for('ob_view', name=ob.name) }} syntax.

However, the models now require a url_for method which is aware of each view that applies to the model. Since models are lower level than views in our hierarchy (models < forms < workflows < views) and lower levels are by intent not supposed to be aware of higher levels, this has been a bad compromise.

UrlForMixin should provide a is_url_for classmethod that can be used to decorate views, to indicate that this view applies to it. Sample use:

from coaster.views import load_model
from .models import Post  # Instance identified by Post.name

@app.route('/view/<post>')
@Post.is_url_for('view', post='name')
@load_model(Post, {'name': 'post'}, 'post')
def post_view(post):  # This expects to receive the Post object
    pass

Like load_model, is_url_for will need assistance knowing what parts of the post are required to construct the URL, but in reverse, including sub-attributes like self.parent.name. To support this, it accepts keyword arguments after the "action" name, where the value of each argument is a string naming the attribute to extract from self, or a tuple containing a recursive set of attributes (like ('parent', 'name')). As a shortcut, a dotted string may be provided, which is broken down into a tuple at decorator-load time.

@jace
Copy link
Member Author

jace commented Dec 2, 2015

is_url_for needs to account for two things:

  1. @app.route may specify a different endpoint name, in which case we can't use the function's name as the endpoint name.
  2. If the view is in a blueprint, we need to call Flask's url_for with <blueprint_name>.<endpoint_name>, but we don't know if this function is in a blueprint. The only distinction is that it has @blueprint.route instead of @app.route.

Given these constraints:

  1. is_url_for should accept blueprint and endpoint as optional parameters, OR
  2. If app.route or blueprint.route leave a marker on the function, it should discover the blueprint and endpoint name from that (most likely they don't because the same function could be used by multiple routes).

@jace
Copy link
Member Author

jace commented Dec 3, 2015

Since blueprint routes are referred to as <blueprint>.<endpoint> in calls to url_for, we don't need them as separate parameters. is_url_for can take a single endpoint parameter that should be a dotted value if used on a view inside a blueprint.

@jace jace closed this as completed in 819b685 Dec 4, 2015
jace added a commit that referenced this issue Dec 4, 2015
is_url_for decorator. Fixes #77.
This was referenced Nov 21, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant