rewrite threads routes to include id

This commit is contained in:
2026-04-20 13:22:41 +03:00
parent a2ceaa0966
commit 7eafcde1d7
6 changed files with 29 additions and 18 deletions

View File

@@ -164,6 +164,7 @@ class Topics(Model):
GROUP BY thread_id GROUP BY thread_id
) )
SELECT SELECT
threads.id,
threads.title, threads.title,
threads.slug, threads.slug,
threads.created_at, threads.created_at,

View File

@@ -62,7 +62,7 @@ def move_thread(thread_id):
if not target_topic: if not target_topic:
abort(404) abort(404)
thread.update({'topic_id': target_topic.id}) thread.update({'topic_id': target_topic.id})
return redirect(url_for('threads.thread', slug=thread.slug)) return redirect(url_for('threads.thread_by_id', thread_id=thread.id))
@bp.post('/threads/<int:thread_id>/lock/') @bp.post('/threads/<int:thread_id>/lock/')
def lock_thread(thread_id): def lock_thread(thread_id):
@@ -70,7 +70,7 @@ def lock_thread(thread_id):
if not thread: if not thread:
abort(404) abort(404)
thread.update({'is_locked': request.form.get('lock')}) thread.update({'is_locked': request.form.get('lock')})
return redirect(url_for('threads.thread', slug=thread.slug)) return redirect(url_for('threads.thread_by_id', thread_id=thread.id))
@bp.post('/threads/<int:thread_id>/sticky/') @bp.post('/threads/<int:thread_id>/sticky/')
def sticky_thread(thread_id): def sticky_thread(thread_id):
@@ -78,7 +78,7 @@ def sticky_thread(thread_id):
if not thread: if not thread:
abort(404) abort(404)
thread.update({'is_stickied': request.form.get('sticky')}) thread.update({'is_stickied': request.form.get('sticky')})
return redirect(url_for('threads.thread', slug=thread.slug)) return redirect(url_for('threads.thread_by_id', thread_id=thread.id))
@bp.post('/users/<int:user_id>/make-guest/') @bp.post('/users/<int:user_id>/make-guest/')
@csrf_verified @csrf_verified

View File

@@ -5,11 +5,21 @@ import math
bp = Blueprint('threads', __name__, url_prefix='/threads/') bp = Blueprint('threads', __name__, url_prefix='/threads/')
@bp.get('/<slug>/') @bp.get('/<int:thread_id>/')
def thread(slug): def thread_by_id(thread_id):
thread = Threads.find({'slug': slug}) thread = Threads.find({'id': thread_id})
if not thread: if not thread:
abort(404) abort(404)
return redirect(url_for('.thread', thread_id=thread_id, slug=thread.slug, **request.args))
@bp.get('/<int:thread_id>/<slug>/')
def thread(thread_id, slug):
thread = Threads.find({'id': thread_id})
if not thread:
abort(404)
if thread.slug != slug:
return redirect(url_for('.thread', thread_id=thread_id, slug=thread.slug, **request.kwargs))
topic = Topics.find({'id': thread.topic_id}) topic = Topics.find({'id': thread.topic_id})
started_by = Users.find({'id': thread.user_id}) started_by = Users.find({'id': thread.user_id})
PER_PAGE = 10 PER_PAGE = 10
@@ -34,21 +44,21 @@ def thread(slug):
abort(404) abort(404)
return render_template('threads/thread.html', thread=thread, posts=thread.get_posts(PER_PAGE, page), page=page, page_count=page_count, topic=topic, started_by=started_by, topics=Topics.get_list(), Reactions=Reactions) return render_template('threads/thread.html', thread=thread, posts=thread.get_posts(PER_PAGE, page), page=page, page_count=page_count, topic=topic, started_by=started_by, topics=Topics.get_list(), Reactions=Reactions)
@bp.post('/<slug>/reply/') @bp.post('/<int:thread_id>/reply/')
@login_required @login_required
def reply(slug): def reply(thread_id):
user = get_active_user() user = get_active_user()
thread = Threads.find({'slug': slug}) thread = Threads.find({'id': thread_id})
if not thread: if not thread:
abort(404) abort(404)
if thread.locked() and not user.is_mod(): if thread.locked() and not user.is_mod():
# TODO: flash # TODO: flash
return redirect(url_for('.thread', slug=slug)) return redirect(url_for('.thread_by_id', thread_id=thread_id))
post = Posts.new(user.id, thread.id, request.form.get('babycode_content')) post = Posts.new(user.id, thread.id, request.form.get('babycode_content'))
return redirect(url_for('.thread', slug=slug, after=post.id, _anchor=f'post-{post.id}')) return redirect(url_for('.thread_by_id', thread_id=thread_id, after=post.id, _anchor=f'post-{post.id}'))
@bp.get('/<slug>/feed.atom/') @bp.get('/<int:thread_id>/feed.atom/')
def feed(slug): def feed(thread_id):
return 'stub' return 'stub'
@bp.get('/new/') @bp.get('/new/')

View File

@@ -23,7 +23,7 @@
<button>Subscribe</button> <button>Subscribe</button>
<button disabled title="This feature requires JavaScript to be enabled.">Bookmark&hellip;</button> <button disabled title="This feature requires JavaScript to be enabled.">Bookmark&hellip;</button>
{%- endif -%} {%- endif -%}
<a href="{{url_for('threads.feed', slug=thread.slug)}}" class="linkbutton rss">Subscribe via RSS</a> <a href="{{url_for('threads.feed', thread_id=thread.id)}}" class="linkbutton rss">Subscribe via RSS</a>
</fieldset> </fieldset>
{%- if is_mod() -%} {%- if is_mod() -%}
<fieldset class="plank even no-shadow minimal thread-actions"> <fieldset class="plank even no-shadow minimal thread-actions">
@@ -64,7 +64,7 @@
</fieldset> </fieldset>
</div> </div>
{%- if is_logged_in() -%} {%- if is_logged_in() -%}
<form action="{{url_for('threads.reply', slug=thread.slug)}}" method="POST" class="plank post-edit-form"> <form action="{{url_for('threads.reply', thread_id=thread.id)}}" method="POST" class="plank post-edit-form">
<h2 class="info">Reply to "{{thread.title}}"</h2> <h2 class="info">Reply to "{{thread.title}}"</h2>
{{- babycode_editor_component() -}} {{- babycode_editor_component() -}}
<span> <span>

View File

@@ -48,10 +48,10 @@
{%- for thread in threads -%} {%- for thread in threads -%}
<div class="topic-info plank"> <div class="topic-info plank">
<div class="title-container"> <div class="title-container">
<span class="info thread-title-counter"><a href="{{url_for('threads.thread', slug=thread.slug)}}">{{thread.title}}</a></span> <span class="info thread-title-counter"><a href="{{url_for('threads.thread_by_id', thread_id=thread.id)}}">{{thread.title}}</a></span>
<ul class="horizontal"></ul> <ul class="horizontal"></ul>
{%- if thread.posts_count / 10 > 1 -%} {%- if thread.posts_count / 10 > 1 -%}
{{pager(0, (((thread.posts_count / 10) | round(0, 'ceil') )| int), 'flex-last', url=url_for('threads.thread', slug=thread.slug))}} {{pager(0, (((thread.posts_count / 10) | round(0, 'ceil') )| int), 'flex-last', url=url_for('threads.thread_by_id', thread_id=thread.id))}}
{%- endif -%} {%- endif -%}
</div> </div>
<span>Started by <a href="{{url_for('users.user_page', username=thread.started_by)}}">{{thread.started_by_display_name if thread.started_by_display_name else thread.started_by}}</a> on {{timestamp(thread.created_at)}}</span> <span>Started by <a href="{{url_for('users.user_page', username=thread.started_by)}}">{{thread.started_by_display_name if thread.started_by_display_name else thread.started_by}}</a> on {{timestamp(thread.created_at)}}</span>

View File

@@ -11,7 +11,7 @@ def get_post_url(post_id, _anchor=False, external=False):
anchor = None if not _anchor else f'post-{post_id}' anchor = None if not _anchor else f'post-{post_id}'
return url_for('threads.thread', slug=thread.slug, after=post_id, _external=external, _anchor=anchor) return url_for('threads.thread_by_id', thread_id=thread.id, after=post_id, _external=external, _anchor=anchor)
def dict_to_query_string(d) -> str: def dict_to_query_string(d) -> str:
return '?' + '&'.join([f'{key}={str(value)}' for key, value in d.items()]) return '?' + '&'.join([f'{key}={str(value)}' for key, value in d.items()])