241 lines
8.4 KiB
Python
241 lines
8.4 KiB
Python
from flask import Blueprint, render_template, request, redirect, url_for, flash
|
||
from app.models import Section, Topic, Subtopic, Keyword
|
||
from app import db
|
||
import logging
|
||
from functools import wraps
|
||
|
||
main = Blueprint('main', __name__)
|
||
|
||
|
||
# 全局上下文處理器,為所有模板提供sections
|
||
@main.context_processor
|
||
def inject_sections():
|
||
def get_sections():
|
||
return Section.query.order_by(Section.order_num).all()
|
||
|
||
return dict(sections=get_sections())
|
||
|
||
|
||
# 錯誤處理裝飾器
|
||
def handle_db_operation(success_message, error_message, redirect_endpoint):
|
||
def decorator(f):
|
||
@wraps(f)
|
||
def wrapped(*args, **kwargs):
|
||
try:
|
||
result = f(*args, **kwargs)
|
||
if isinstance(result, bool) and result:
|
||
db.session.commit()
|
||
flash(success_message, 'success')
|
||
return redirect(url_for(redirect_endpoint))
|
||
return result
|
||
except Exception as e:
|
||
db.session.rollback()
|
||
logging.error(f"資料庫錯誤: {str(e)}")
|
||
flash(error_message, 'danger')
|
||
return redirect(url_for('main.admin'))
|
||
|
||
return wrapped
|
||
|
||
return decorator
|
||
|
||
|
||
# 基本路由
|
||
@main.route('/')
|
||
def index():
|
||
return render_template('index.html')
|
||
|
||
|
||
@main.route('/section/<int:section_id>')
|
||
def section(section_id):
|
||
section = Section.query.get_or_404(section_id)
|
||
return render_template('section.html',
|
||
section=section,
|
||
active_section=section_id)
|
||
|
||
|
||
@main.route('/admin')
|
||
def admin():
|
||
return render_template('admin/index.html')
|
||
|
||
|
||
# 區塊管理
|
||
@main.route('/admin/sections')
|
||
def manage_sections():
|
||
sections = Section.query.order_by(Section.order_num).all()
|
||
return render_template('admin/sections.html', sections=sections)
|
||
|
||
|
||
@main.route('/admin/section/add', methods=['GET', 'POST'])
|
||
@handle_db_operation('區塊新增成功!', '區塊新增失敗!', 'main.manage_sections')
|
||
def add_section():
|
||
if request.method == 'POST':
|
||
section = Section(
|
||
title=request.form['title'],
|
||
order_num=int(request.form['order_num'])
|
||
)
|
||
db.session.add(section)
|
||
return True
|
||
return render_template('admin/section_form.html')
|
||
|
||
|
||
@main.route('/admin/section/edit/<int:section_id>', methods=['GET', 'POST'])
|
||
@handle_db_operation('區塊更新成功!', '區塊更新失敗!', 'main.manage_sections')
|
||
def edit_section(section_id):
|
||
section = Section.query.get_or_404(section_id)
|
||
if request.method == 'POST':
|
||
section.title = request.form['title']
|
||
section.order_num = int(request.form['order_num'])
|
||
return True
|
||
return render_template('admin/section_form.html', section=section)
|
||
|
||
|
||
@main.route('/admin/section/delete/<int:section_id>')
|
||
@handle_db_operation('區塊刪除成功!', '區塊刪除失敗!', 'main.manage_sections')
|
||
def delete_section(section_id):
|
||
section = Section.query.get_or_404(section_id)
|
||
db.session.delete(section)
|
||
return True
|
||
|
||
|
||
# 主題管理
|
||
@main.route('/admin/topics')
|
||
def manage_topics():
|
||
topics = Topic.query.all()
|
||
return render_template('admin/topics.html', topics=topics)
|
||
|
||
|
||
@main.route('/admin/topic/add', methods=['GET', 'POST'])
|
||
@handle_db_operation('主題新增成功!', '主題新增失敗!', 'main.manage_topics')
|
||
def add_topic():
|
||
if request.method == 'POST':
|
||
topic = Topic(
|
||
section_id=int(request.form['section_id']),
|
||
title=request.form['title'],
|
||
description=request.form['description']
|
||
)
|
||
db.session.add(topic)
|
||
return True
|
||
return render_template('admin/topic_form.html', sections=Section.query.all())
|
||
|
||
|
||
@main.route('/admin/topic/edit/<int:topic_id>', methods=['GET', 'POST'])
|
||
@handle_db_operation('主題更新成功!', '主題更新失敗!', 'main.manage_topics')
|
||
def edit_topic(topic_id):
|
||
topic = Topic.query.get_or_404(topic_id)
|
||
if request.method == 'POST':
|
||
topic.section_id = int(request.form['section_id'])
|
||
topic.title = request.form['title']
|
||
topic.description = request.form['description']
|
||
return True
|
||
return render_template('admin/topic_form.html', topic=topic, sections=Section.query.all())
|
||
|
||
|
||
@main.route('/admin/topic/delete/<int:topic_id>')
|
||
@handle_db_operation('主題刪除成功!', '主題刪除失敗!', 'main.manage_topics')
|
||
def delete_topic(topic_id):
|
||
topic = Topic.query.get_or_404(topic_id)
|
||
db.session.delete(topic)
|
||
return True
|
||
|
||
|
||
# 子知識點管理
|
||
@main.route('/admin/subtopics')
|
||
def manage_subtopics():
|
||
subtopics = Subtopic.query.all()
|
||
return render_template('admin/subtopics.html', subtopics=subtopics)
|
||
|
||
|
||
@main.route('/admin/subtopic/add', methods=['GET', 'POST'])
|
||
@handle_db_operation('子知識點新增成功!', '子知識點新增失敗!', 'main.manage_subtopics')
|
||
def add_subtopic():
|
||
if request.method == 'POST':
|
||
subtopic = Subtopic(
|
||
topic_id=int(request.form['topic_id']),
|
||
title=request.form['title'],
|
||
content=request.form['content']
|
||
)
|
||
if 'keywords' in request.form:
|
||
keyword_ids = request.form.getlist('keywords')
|
||
subtopic.keywords = Keyword.query.filter(Keyword.id.in_(keyword_ids)).all()
|
||
db.session.add(subtopic)
|
||
return True
|
||
return render_template('admin/subtopic_form.html',
|
||
topics=Topic.query.all(),
|
||
keywords=Keyword.query.all())
|
||
|
||
|
||
@main.route('/admin/subtopic/edit/<int:subtopic_id>', methods=['GET', 'POST'])
|
||
@handle_db_operation('子知識點更新成功!', '子知識點更新失敗!', 'main.manage_subtopics')
|
||
def edit_subtopic(subtopic_id):
|
||
subtopic = Subtopic.query.get_or_404(subtopic_id)
|
||
if request.method == 'POST':
|
||
subtopic.topic_id = int(request.form['topic_id'])
|
||
subtopic.title = request.form['title']
|
||
subtopic.content = request.form['content']
|
||
if 'keywords' in request.form:
|
||
keyword_ids = request.form.getlist('keywords')
|
||
subtopic.keywords = Keyword.query.filter(Keyword.id.in_(keyword_ids)).all()
|
||
return True
|
||
return render_template('admin/subtopic_form.html',
|
||
subtopic=subtopic,
|
||
topics=Topic.query.all(),
|
||
keywords=Keyword.query.all())
|
||
|
||
|
||
@main.route('/admin/subtopic/delete/<int:subtopic_id>')
|
||
@handle_db_operation('子知識點刪除成功!', '子知識點刪除失敗!', 'main.manage_subtopics')
|
||
def delete_subtopic(subtopic_id):
|
||
subtopic = Subtopic.query.get_or_404(subtopic_id)
|
||
db.session.delete(subtopic)
|
||
return True
|
||
|
||
|
||
# 關鍵字管理
|
||
@main.route('/admin/keywords')
|
||
def manage_keywords():
|
||
keywords = Keyword.query.all()
|
||
return render_template('admin/keywords.html', keywords=keywords)
|
||
|
||
|
||
@main.route('/admin/keyword/add', methods=['GET', 'POST'])
|
||
@handle_db_operation('關鍵字新增成功!', '關鍵字新增失敗!', 'main.manage_keywords')
|
||
def add_keyword():
|
||
if request.method == 'POST':
|
||
if Keyword.query.filter_by(term=request.form['term']).first():
|
||
flash('此關鍵字已存在!', 'warning')
|
||
return redirect(url_for('main.add_keyword'))
|
||
|
||
keyword = Keyword(
|
||
term=request.form['term'],
|
||
description=request.form['description']
|
||
)
|
||
db.session.add(keyword)
|
||
return True
|
||
return render_template('admin/keyword_form.html')
|
||
|
||
|
||
@main.route('/admin/keyword/edit/<int:keyword_id>', methods=['GET', 'POST'])
|
||
@handle_db_operation('關鍵字更新成功!', '關鍵字更新失敗!', 'main.manage_keywords')
|
||
def edit_keyword(keyword_id):
|
||
keyword = Keyword.query.get_or_404(keyword_id)
|
||
if request.method == 'POST':
|
||
if Keyword.query.filter(
|
||
Keyword.term == request.form['term'],
|
||
Keyword.id != keyword_id
|
||
).first():
|
||
flash('此關鍵字已存在!', 'warning')
|
||
return redirect(url_for('main.edit_keyword', keyword_id=keyword_id))
|
||
|
||
keyword.term = request.form['term']
|
||
keyword.description = request.form['description']
|
||
return True
|
||
return render_template('admin/keyword_form.html', keyword=keyword)
|
||
|
||
|
||
@main.route('/admin/keyword/delete/<int:keyword_id>')
|
||
@handle_db_operation('關鍵字刪除成功!', '關鍵字刪除失敗!', 'main.manage_keywords')
|
||
def delete_keyword(keyword_id):
|
||
keyword = Keyword.query.get_or_404(keyword_id)
|
||
db.session.delete(keyword)
|
||
return True
|