PCv5/app/utils/converters.py
Lephe 8a0ba309e0
forum: restructure models and add topic creation
This changes fixes #25 by restructuring the forum models in a way
compatible with the polymorphic behavior of SQLAlchemy. Incidentally,
the new form turns out to be more appropriate for our use than the
polymorphic one originally used.

The migration for this task is non-trivial because the Thread class was
created with a foreign-key id which thus had no auto-increment or
associated sequence. The most reliable way of getting it back was to
recreate the table because SQLAlchemy ony performs automated sequence
introduction at table creation time. Four separate migration files
perform the whole change.

This commit also adds views and forms to create topics, and the
boilerplate for an advanced markup editor that can be used as a widget.
2019-09-09 08:11:38 +02:00

58 lines
1.9 KiB
Python

"""
utils.converter: Custom URL converters to match patterns in @app.route()
The Flask documentation is elusive on this topic. To add a new converter,
proceed as follows:
1. Define a new converter class.
2. Set the [regex] attribute to decide which portion of the URL will be
considered for conversion (apparently the default is everything until next
slash or end of string).
3. Define the to_python() and to_url() methods to actually convert.
4. Add the class to __all__ at the bottom of this file.
5. In app/__init__.py, add a dictionary entry to [app.url_map.converters].
For more information, see the Werkzeug documentation:
<https://werkzeug.palletsprojects.com/en/0.15.x/routing/#custom-converters>
"""
from werkzeug.routing import BaseConverter, ValidationError
from app.models.forum import Forum
import re
import sys
class ForumConverter(BaseConverter):
# This regex will decide which portion of the URL is matched by the curtom
# converter. By default, slashes are not included, so we must add them.
regex = r'[a-z/]+'
def to_python(self, url):
url = '/' + url
f = Forum.query.filter_by(url=url).first()
if f is None:
raise ValidationError(f"ForumConverter: no forum with url {url}")
return f
def to_url(self, forum):
return forum.url[1:]
class TopicSlugConverter(BaseConverter):
# Only catch integers followed by an optional slug string
regex = r'(\d+)(?:-[\w-]*)?'
def to_python(self, url):
"""Convert an URL pattern to a Python object, or raise an exception."""
m = re.fullmatch(TopicSlugConverter.regex, url)
if m is None:
raise Exception(f"TopicSlugConverter: conversation failed")
return int(m[1], 10)
def to_url(self, topic_id):
return str(topic_id)
# Export only the converter classes
__all__ = "ForumConverter TopicSlugConverter".split()