rewrite using pyramid and wtforms

This commit is contained in:
evilchili
2024-01-31 22:39:54 -08:00
parent 5faf5c97c1
commit 3444f83c91
15 changed files with 234 additions and 163 deletions
+5
View File
@@ -10,9 +10,14 @@ from ttfrog.webserver.routes import routes
def configuration():
config = Configurator(settings={
'sqlalchemy.url': db.url,
'jinja2.directories': 'ttfrog.assets:templates/'
})
config.include('pyramid_tm')
config.include('pyramid_sqlalchemy')
config.include('pyramid_jinja2')
config.add_static_view(name='/static', path='ttfrog.assets:static/')
config.add_jinja2_renderer('.html', settings_prefix='jinja2.')
return config
+4
View File
@@ -0,0 +1,4 @@
from .base import BaseController
from .character_sheet import CharacterSheet
__all__ = [BaseController, CharacterSheet]
+65 -10
View File
@@ -1,19 +1,74 @@
import inspect
import logging
from collections import defaultdict
from tg import flash
from tg import TGController
from tg import tmpl_context
from markupsafe import Markup
from wtforms_sqlalchemy.orm import model_form
from ttfrog.db.manager import db
class BaseController(TGController):
class BaseController:
model = None
def _before(self, *args, **kwargs):
tmpl_context.project_name = 'TableTop Frog'
def __init__(self, request):
self.request = request
self.record = None
self.attrs = defaultdict(str)
self.configure()
if self.model:
self.model_form = model_form(self.model, db_session=db.session)
# load this from dotenv or something
self.config = {
'static_url': '/static',
'project_name': 'TTFROG'
}
def configure(self):
self.load_from_id()
def load_from_id(self):
if not self.request.POST['id']:
return
self.record = db.query(self.model).get(self.request.POST['id'])
def form(self) -> str:
# no model? no form.
if not self.model:
return ''
# no user submission to process
if self.request.method != 'POST':
return self.model_form(obj=self.record)
# process submission
form = self.model_form(self.request.POST, obj=self.record)
if self.model.validate(form):
form.populate_obj(self.record)
error = self.save_changes()
if error:
form.errors['process'] = error
return form
def save_changes(self):
try:
with db.transaction():
for (key, val) in self.request.POST.items():
if hasattr(self.record, key):
setattr(self.record, key, val)
except Exception as e:
return e
return None
def output(self, **kwargs) -> dict:
return dict(
page=inspect.stack()[1].function,
flash=Markup(flash.render('flash', use_js=False)),
config=self.config,
request=self.request,
record=self.record,
form=self.form(),
**self.attrs,
**kwargs,
)
def response(self):
return self.output()
+12 -64
View File
@@ -1,72 +1,20 @@
import base64
import hashlib
import logging
from tg import expose
from tg import flash
from tg import validate
from tg.controllers.util import redirect
from ttfrog.db import db
from ttfrog.webserver.controllers import BaseController
from ttfrog.db.manager import db
from ttfrog.db.schema import Character
from ttfrog.webserver.controllers.base import BaseController
from ttfrog.webserver.widgets import CharacterSheet
class CharacterSheetController(BaseController):
@expose()
def _lookup(self, *parts):
slug = parts[0] if parts else ''
return FormController(slug), parts[1:] if len(parts) > 1 else []
class CharacterSheet(BaseController):
model = Character
class FormController(BaseController):
def __init__(self, slug: str):
super().__init__()
self.character = dict()
def configure(self):
self.attrs['all_characters'] = db.query(Character).all()
slug = self.request.matchdict.get('slug', None)
if slug:
self.load_from_slug(slug)
@property
def uri(self):
if self.character:
return f"/sheet/{self.character['slug']}/{self.character['name']}"
try:
self.record = db.query(Character).filter(Character.slug == slug)[0]
except IndexError:
logging.warning(f"Could not load record with slug {slug}")
else:
return None
@property
def all_characters(self):
return [row._mapping for row in db.query(Character).all()]
def load_from_slug(self, slug) -> None:
self.character = db.query(Character).filter(Character.columns.slug == slug)[0]._mapping
def save(self, fields) -> str:
rec = dict()
if not self.character:
result, error = db.insert(Character, **fields)
if error:
return error
fields['id'] = result.inserted_primary_key[0]
fields['slug'] = db.slugify(fields)
else:
rec = dict(**self.character)
rec.update(**fields)
result, error = db.update(Character, **rec)
self.load_from_slug(rec['slug'])
if not error:
flash(f"{self.character['name']} updated!")
return redirect(self.uri)
flash(error)
@expose('character_sheet.html')
@validate(form=CharacterSheet)
def _default(self, *args, **fields):
if fields:
return self.save(fields)
return self.output(
form=CharacterSheet,
character=self.character,
all_characters=self.all_characters,
)
self.load_from_id()
-16
View File
@@ -1,16 +0,0 @@
from tg import expose
from ttfrog.db import db
from ttfrog.webserver.controllers.base import BaseController
from ttfrog.webserver.controllers.character_sheet import CharacterSheetController
class RootController(BaseController):
# serve character sheet interface on /sheet
sheet = CharacterSheetController()
@expose('index.html')
def index(self):
ancestries = [row._mapping for row in db.query(db.ancestry).all()]
return self.output(content=str(ancestries))
+1
View File
@@ -1,2 +1,3 @@
def routes(config):
config.add_route('index', '/')
config.add_route('sheet', '/sheet/{slug}/{name}', factory='ttfrog.webserver.controllers.CharacterSheet')
+6
View File
@@ -8,3 +8,9 @@ from ttfrog.db.schema import Ancestry
def index(request):
ancestries = [a.name for a in db.session.query(Ancestry).all()]
return Response(','.join(ancestries))
@view_config(route_name='sheet', renderer='character_sheet.html')
def sheet(request):
sheet = request.context
return sheet.response()