Compare commits

...

1 Commits

Author SHA1 Message Date
2c2c94c2eb Some fixes and updates
- Fix some relationships in the models
- Set up theming system based on user setting
- Use the "/node" endpoint for nodes, rather than "/" which will become
  problematic.
2024-12-06 22:47:11 -06:00
3 changed files with 39 additions and 21 deletions

View File

@ -25,6 +25,8 @@ class NodeType(Model):
slug: Mapped[str] = mapped_column(String(255), nullable=False, index=True) slug: Mapped[str] = mapped_column(String(255), nullable=False, index=True)
description: Mapped[str] = mapped_column(Text) description: Mapped[str] = mapped_column(Text)
fields: Mapped[list['NodeField']] = relationship(back_populates='node_type')
class NodeRevision(Model): class NodeRevision(Model):
"""A revision of a content node""" """A revision of a content node"""
@ -34,6 +36,7 @@ class NodeRevision(Model):
node_id: Mapped[int] = mapped_column(Integer, ForeignKey('nodes.id')) node_id: Mapped[int] = mapped_column(Integer, ForeignKey('nodes.id'))
revision: Mapped[int] = mapped_column(Integer, default=1) revision: Mapped[int] = mapped_column(Integer, default=1)
node: Mapped['Node'] = relationship(back_populates='revisions')
fields: Mapped[list['NodeFieldInstance']] = relationship(secondary=revisions_fields_table, fields: Mapped[list['NodeFieldInstance']] = relationship(secondary=revisions_fields_table,
back_populates='node_revision') back_populates='node_revision')
@ -73,7 +76,7 @@ class NodeField(Model):
slug: Mapped[str] = mapped_column(String(255), nullable=False, unique=True, index=True) slug: Mapped[str] = mapped_column(String(255), nullable=False, unique=True, index=True)
field_type: Mapped[str] = mapped_column(String(255)) field_type: Mapped[str] = mapped_column(String(255))
node_type: Mapped['NodeType'] = relationship(back_populates='node_fields') node_type: Mapped['NodeType'] = relationship(back_populates='fields')
class NodeFieldInstance(Model): class NodeFieldInstance(Model):
@ -82,6 +85,8 @@ class NodeFieldInstance(Model):
id: Mapped[int] = mapped_column(Integer, primary_key=True) id: Mapped[int] = mapped_column(Integer, primary_key=True)
node_field_id: Mapped[int] = mapped_column(Integer, ForeignKey('node_fields.id')) node_field_id: Mapped[int] = mapped_column(Integer, ForeignKey('node_fields.id'))
revision_id: Mapped[int] = mapped_column(Integer, ForeignKey('node_revisions.id'))
value: Mapped[str] = mapped_column(Text) value: Mapped[str] = mapped_column(Text)
node_field: Mapped['NodeField'] = relationship() node_field: Mapped['NodeField'] = relationship()
node_revision: Mapped['NodeRevision'] = relationship(back_populates='fields')

View File

@ -1,5 +1,13 @@
from flask_theme import get_theme, render_theme_template, template_exists
from quart import Quart, current_app, request from quart import Quart, current_app, request
from flask_theme import get_theme, render_theme_template from sqlalchemy.query import select
from scribeengine.db.base import Session
from scribeengine.db.models.settings import SettingValue
class TemplateNotExistsError(Exception):
pass
def register_globals(app: Quart) -> None: def register_globals(app: Quart) -> None:
@ -13,11 +21,18 @@ def register_globals(app: Quart) -> None:
def get_current_theme(): def get_current_theme():
"""Get the current theme""" """Get the current theme"""
ident = current_app.config.get('DEFAULT_THEME', 'quill') default_theme = current_app.config.get('DEFAULT_THEME', 'quill')
return get_theme(ident) with Session as session:
theme_setting = session.scalars(select(SettingValue).where(SettingValue.key.slug == 'theme')).first()
if theme_setting:
return get_theme(theme_setting.get_value())
return get_theme(default_theme)
def render(template, **context): def render(templates: list[str], **context):
"""Render the template using the current theme""" """Render the template using the current theme"""
theme = get_current_theme() theme = get_current_theme()
return render_theme_template(theme, template, **context) for template in templates:
if template_exists(template):
return render_theme_template(theme, template, **context)
raise TemplateNotExistsError()

View File

@ -1,13 +1,14 @@
from typing import Union from typing import Union
from quart import Blueprint, render_template, request, abort from quart import Blueprint, request, abort
from sqlalchemy.sql import select from sqlalchemy.sql import select
from scribeengine.db.base import Session from scribeengine.db.base import Session
from scribeengine.db.models.node import Node from scribeengine.db.models.node import Node
from scribeengine.util.nodes import get_node, get_node_templates from scribeengine.util.nodes import get_node, get_node_templates
from scribeengine.templating import render
nodes = Blueprint('nodes', __name__, url_prefix='/') nodes = Blueprint('nodes', __name__, url_prefix='/node')
def _get_node_list(*filters) -> tuple[int, int, list[Node]]: def _get_node_list(*filters) -> tuple[int, int, list[Node]]:
@ -24,27 +25,24 @@ def _get_node_list(*filters) -> tuple[int, int, list[Node]]:
@nodes.route('', methods=['GET']) @nodes.route('', methods=['GET'])
async def list_nodes():
"""List all the nodes"""
page, page_size, node_list = _get_node_list()
all_nodes = [get_node(node) for node in node_list]
return await render_template('admin/nodes/list_nodes.html', nodes=all_nodes, page=page, page_size=page_size)
@nodes.route('/<node_type>', methods=['GET']) @nodes.route('/<node_type>', methods=['GET'])
async def list_nodes_by_type(node_type: str): async def list_nodes(node_type: str | None = None):
"""List all the nodes""" """List all the nodes"""
page, page_size, node_list = _get_node_list(Node.node_type.slug == node_type) if node_type:
page, page_size, node_list = _get_node_list(Node.node_Type.slug == node_type)
else:
page, page_size, node_list = _get_node_list()
all_nodes = [get_node(node) for node in node_list] all_nodes = [get_node(node) for node in node_list]
node_templates = get_node_templates(node_type, 'list') node_templates = get_node_templates('node', 'list')
return await render_template(node_templates, nodes=all_nodes, page=page, page_size=page_size) node_templates.insert(0, 'front_page.html')
return await render('nodes/list_nodes.html', nodes=all_nodes, page=page, page_size=page_size)
@nodes.route('<slug_or_id>', methods=['GET']) @nodes.route('/by-slug/<slug_or_id>', methods=['GET'])
async def view_node(slug_or_id: Union[str, int]): async def view_node(slug_or_id: Union[str, int]):
"""View a single node""" """View a single node"""
node = get_node(slug_or_id) node = get_node(slug_or_id)
if not node: if not node:
return await abort(404) return await abort(404)
node_templates = get_node_templates(node['node_type'], 'view') node_templates = get_node_templates(node['node_type'], 'view')
return await render_template(node_templates, node=node) return await render(node_templates, node=node)