Create the RoutedMixin class
It will be used both in the app, and later blueprint classes.
This commit is contained in:
parent
89dc258a5b
commit
8d45611e35
@ -25,6 +25,8 @@ from flask_babelex import Babel, get_locale as babel_get_locale
|
||||
from flask_security import SQLAlchemyUserDatastore, current_user, login_required
|
||||
from sqlalchemy.orm.exc import NoResultFound, MultipleResultsFound
|
||||
|
||||
from calsocial.utils import RoutedMixin
|
||||
|
||||
|
||||
def get_locale():
|
||||
"""Locale selector
|
||||
@ -53,22 +55,7 @@ def template_vars():
|
||||
}
|
||||
|
||||
|
||||
def route(*args, **kwargs):
|
||||
"""Mark a function as a future route
|
||||
|
||||
Such functions will be iterated over when the application is initialised. ``*args`` and
|
||||
``**kwargs`` will be passed verbatim to `Flask.route()`.
|
||||
"""
|
||||
|
||||
def decorator(func): # pylint: disable=missing-docstring
|
||||
setattr(func, 'routing', (args, kwargs))
|
||||
|
||||
return func
|
||||
|
||||
return decorator
|
||||
|
||||
|
||||
class CalendarSocialApp(Flask):
|
||||
class CalendarSocialApp(Flask, RoutedMixin):
|
||||
"""The Calendar.social app
|
||||
"""
|
||||
|
||||
@ -101,18 +88,7 @@ class CalendarSocialApp(Flask):
|
||||
|
||||
self.context_processor(template_vars)
|
||||
|
||||
for attr_name in self.__dir__():
|
||||
attr = getattr(self, attr_name)
|
||||
|
||||
if not callable(attr):
|
||||
continue
|
||||
|
||||
args, kwargs = getattr(attr, 'routing', (None, None))
|
||||
|
||||
if args is None:
|
||||
continue
|
||||
|
||||
self.route(*args, **kwargs)(attr)
|
||||
RoutedMixin.register_routes(self)
|
||||
|
||||
self.before_request(self.goto_first_steps)
|
||||
|
||||
@ -165,7 +141,7 @@ class CalendarSocialApp(Flask):
|
||||
|
||||
return GregorianCalendar(timestamp.timestamp())
|
||||
|
||||
@route('/about')
|
||||
@RoutedMixin.route('/about')
|
||||
def about(self):
|
||||
"""View for the about page
|
||||
"""
|
||||
@ -190,7 +166,7 @@ class CalendarSocialApp(Flask):
|
||||
user_count=user_count,
|
||||
event_count=event_count)
|
||||
|
||||
@route('/')
|
||||
@RoutedMixin.route('/')
|
||||
def hello(self):
|
||||
"""View for the main page
|
||||
|
||||
@ -206,7 +182,7 @@ class CalendarSocialApp(Flask):
|
||||
return render_template('index.html', calendar=calendar, user_only=True)
|
||||
|
||||
@staticmethod
|
||||
@route('/register', methods=['POST', 'GET'])
|
||||
@RoutedMixin.route('/register', methods=['POST', 'GET'])
|
||||
def register():
|
||||
"""View for user registration
|
||||
|
||||
@ -236,7 +212,7 @@ class CalendarSocialApp(Flask):
|
||||
return render_template('registration.html', form=form)
|
||||
|
||||
@staticmethod
|
||||
@route('/new-event', methods=['GET', 'POST'])
|
||||
@RoutedMixin.route('/new-event', methods=['GET', 'POST'])
|
||||
@login_required
|
||||
def new_event():
|
||||
"""View for creating a new event
|
||||
@ -261,7 +237,7 @@ class CalendarSocialApp(Flask):
|
||||
return render_template('event-edit.html', form=form)
|
||||
|
||||
@staticmethod
|
||||
@route('/settings', methods=['GET', 'POST'])
|
||||
@RoutedMixin.route('/settings', methods=['GET', 'POST'])
|
||||
@login_required
|
||||
def settings():
|
||||
"""View for user settings
|
||||
@ -282,7 +258,7 @@ class CalendarSocialApp(Flask):
|
||||
return render_template('user-settings.html', form=form)
|
||||
|
||||
@staticmethod
|
||||
@route('/event/<string:event_uuid>', methods=['GET', 'POST'])
|
||||
@RoutedMixin.route('/event/<string:event_uuid>', methods=['GET', 'POST'])
|
||||
def event_details(event_uuid):
|
||||
"""View to display event details
|
||||
"""
|
||||
@ -309,7 +285,7 @@ class CalendarSocialApp(Flask):
|
||||
return render_template('event-details.html', event=event, form=form)
|
||||
|
||||
@staticmethod
|
||||
@route('/profile/@<string:username>')
|
||||
@RoutedMixin.route('/profile/@<string:username>')
|
||||
def display_profile(username):
|
||||
"""View to display profile details
|
||||
"""
|
||||
@ -324,7 +300,7 @@ class CalendarSocialApp(Flask):
|
||||
return render_template('profile-details.html', profile=profile)
|
||||
|
||||
@staticmethod
|
||||
@route('/profile/@<string:username>/follow')
|
||||
@RoutedMixin.route('/profile/@<string:username>/follow')
|
||||
@login_required
|
||||
def follow_user(username):
|
||||
"""View for following a user
|
||||
@ -345,7 +321,7 @@ class CalendarSocialApp(Flask):
|
||||
return redirect(url_for('display_profile', username=username))
|
||||
|
||||
@staticmethod
|
||||
@route('/notifications')
|
||||
@RoutedMixin.route('/notifications')
|
||||
def notifications():
|
||||
"""View to list the notifications for the current user
|
||||
"""
|
||||
@ -360,7 +336,7 @@ class CalendarSocialApp(Flask):
|
||||
return render_template('notifications.html', notifs=notifs)
|
||||
|
||||
@staticmethod
|
||||
@route('/accept/<int:invite_id>')
|
||||
@RoutedMixin.route('/accept/<int:invite_id>')
|
||||
def accept_invite(invite_id):
|
||||
"""View to accept an invitation
|
||||
"""
|
||||
@ -390,7 +366,7 @@ class CalendarSocialApp(Flask):
|
||||
return redirect(url_for('event_details', event_uuid=invitation.event.event_uuid))
|
||||
|
||||
@staticmethod
|
||||
@route('/first-steps', methods=['GET', 'POST'])
|
||||
@RoutedMixin.route('/first-steps', methods=['GET', 'POST'])
|
||||
@login_required
|
||||
def first_steps():
|
||||
"""View to set up a new registrant’s profile
|
||||
@ -417,7 +393,7 @@ class CalendarSocialApp(Flask):
|
||||
return render_template('first-steps.html', form=form)
|
||||
|
||||
@staticmethod
|
||||
@route('/edit-profile', methods=['GET', 'POST'])
|
||||
@RoutedMixin.route('/edit-profile', methods=['GET', 'POST'])
|
||||
@login_required
|
||||
def edit_profile():
|
||||
"""View for editing one’s profile
|
||||
@ -438,7 +414,7 @@ class CalendarSocialApp(Flask):
|
||||
return render_template('profile-edit.html', form=form)
|
||||
|
||||
@staticmethod
|
||||
@route('/all-events')
|
||||
@RoutedMixin.route('/all-events')
|
||||
def all_events():
|
||||
"""View for listing all available events
|
||||
"""
|
||||
@ -455,7 +431,7 @@ class CalendarSocialApp(Flask):
|
||||
return render_template('index.html', calendar=calendar, user_only=False)
|
||||
|
||||
@staticmethod
|
||||
@route('/follow-requests')
|
||||
@RoutedMixin.route('/follow-requests')
|
||||
@login_required
|
||||
def follow_requests():
|
||||
"""View for listing follow requests
|
||||
@ -470,7 +446,7 @@ class CalendarSocialApp(Flask):
|
||||
return render_template('follow-requests.html', requests=requests)
|
||||
|
||||
@staticmethod
|
||||
@route('/follow-request/<int:follower_id>/accept')
|
||||
@RoutedMixin.route('/follow-request/<int:follower_id>/accept')
|
||||
@login_required
|
||||
def accept_follow(follower_id):
|
||||
"""View for accepting a follow request
|
||||
|
@ -68,3 +68,51 @@ def force_locale(locale):
|
||||
babel.locale_selector_func = orig_locale_selector_func
|
||||
for key, value in orig_attrs.items():
|
||||
setattr(ctx, key, value)
|
||||
|
||||
|
||||
class RoutedMixin:
|
||||
"""Mixin to lazily register class methods as routes
|
||||
|
||||
Works both for `Flask` and `Blueprint` objects.
|
||||
|
||||
Example::
|
||||
|
||||
class MyBlueprint(Blueprint, RoutedMixin):
|
||||
def __init__(self, *args, **kwargs):
|
||||
do_whatever_you_like()
|
||||
|
||||
RoutedMixin.register_routes(self)
|
||||
|
||||
@RoutedMixin.route('/')
|
||||
def index(self):
|
||||
return 'Hello, World!'
|
||||
"""
|
||||
|
||||
def register_routes(self):
|
||||
for attr_name in self.__dir__():
|
||||
attr = getattr(self, attr_name)
|
||||
|
||||
if not callable(attr):
|
||||
continue
|
||||
|
||||
args, kwargs = getattr(attr, 'routing', (None, None))
|
||||
|
||||
if args is None:
|
||||
continue
|
||||
|
||||
self.route(*args, **kwargs)(attr)
|
||||
|
||||
@staticmethod
|
||||
def route(*args, **kwargs):
|
||||
"""Mark a function as a future route
|
||||
|
||||
Such functions will be iterated over when the application is initialised. ``*args`` and
|
||||
``**kwargs`` will be passed verbatim to `Flask.route()`.
|
||||
"""
|
||||
|
||||
def decorator(func): # pylint: disable=missing-docstring
|
||||
setattr(func, 'routing', (args, kwargs))
|
||||
|
||||
return func
|
||||
|
||||
return decorator
|
||||
|
Loading…
Reference in New Issue
Block a user