Lephe
8a0ba309e0
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.
58 lines
1.9 KiB
Python
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()
|