tabletop-frog/ttfrog/webserver/controllers/base.py

155 lines
4.4 KiB
Python
Raw Normal View History

2024-02-01 00:28:17 -08:00
import logging
2024-02-02 15:40:45 -08:00
import re
2024-01-28 22:14:50 -08:00
2024-02-04 11:40:30 -08:00
from collections import defaultdict
2024-01-28 22:14:50 -08:00
2024-02-02 15:40:45 -08:00
from pyramid.httpexceptions import HTTPFound
from pyramid.interfaces import IRoutesMapper
2024-02-04 11:40:30 -08:00
2024-01-31 22:39:54 -08:00
from ttfrog.db.manager import db
2024-02-08 01:14:35 -08:00
from ttfrog.db import transaction_log
2024-01-28 22:14:50 -08:00
2024-02-02 15:40:45 -08:00
def get_all_routes(request):
2024-02-04 11:40:30 -08:00
routes = {
'static': '/static',
}
2024-02-02 15:40:45 -08:00
uri_pattern = re.compile(r"^([^\{\*]+)")
mapper = request.registry.queryUtility(IRoutesMapper)
for route in mapper.get_routes():
if route.name.startswith('__'):
continue
m = uri_pattern.search(route.pattern)
if m:
routes[route.name] = m .group(0)
return routes
2024-01-31 22:39:54 -08:00
class BaseController:
model = None
2024-02-04 11:40:30 -08:00
model_form = None
2024-01-31 22:39:54 -08:00
def __init__(self, request):
self.request = request
self.attrs = defaultdict(str)
2024-02-04 11:40:30 -08:00
self._slug = None
self._record = None
self._form = None
2024-01-31 22:39:54 -08:00
self.config = {
'static_url': '/static',
'project_name': 'TTFROG'
}
2024-02-01 00:28:17 -08:00
self.configure_for_model()
2024-02-04 11:40:30 -08:00
@property
def slug(self):
if not self._slug:
parts = self.request.matchdict.get('uri', '').split('-')
self._slug = parts[0].replace('/', '')
return self._slug
@property
def record(self):
if not self._record and self.model:
try:
self._record = db.query(self.model).filter(self.model.slug == self.slug)[0]
except IndexError:
logging.warning(f"Could not load record with slug {self.slug}")
self._record = self.model()
return self._record
@property
def form(self):
2024-02-01 00:28:17 -08:00
if not self.model:
return
if not self.model_form:
return
2024-02-04 11:40:30 -08:00
if not self._form:
if self.request.POST:
self._form = self.model_form(self.request.POST, obj=self.record)
else:
self._form = self.model_form(obj=self.record)
if not self.record.id:
2024-02-23 10:45:38 -08:00
# apply the db schema defaults
self._form.process()
2024-02-04 11:40:30 -08:00
return self._form
2024-02-01 00:28:17 -08:00
2024-02-08 01:14:35 -08:00
@property
def resources(self):
return [
{'type': 'style', 'uri': 'css/styles.css'},
]
2024-02-04 11:40:30 -08:00
def configure_for_model(self):
2024-02-01 00:28:17 -08:00
if 'all_records' not in self.attrs:
self.attrs['all_records'] = db.query(self.model).all()
2024-02-04 11:40:30 -08:00
def template_context(self, **kwargs) -> dict:
return dict(
config=self.config,
request=self.request,
form=self.form,
record=self.record,
routes=get_all_routes(self.request),
resources=self.resources,
**self.attrs,
**kwargs,
)
2024-01-31 22:39:54 -08:00
2024-02-23 10:45:38 -08:00
def populate(self):
self.form.populate_obj(self.record)
def populate_association(self, key, formdata):
populated = []
for field in formdata:
map_id = field.pop('id')
map_id = int(map_id) if map_id else 0
if not field[key]:
continue
elif not map_id:
populated.append(field)
else:
field['id'] = map_id
populated.append(field)
return populated
def validate(self):
return self.form.validate()
2024-02-04 15:22:54 -08:00
def save(self):
if not self.form.save.data:
return
if not self.validate():
2024-02-04 15:22:54 -08:00
return
2024-02-23 10:45:38 -08:00
logging.debug(f"{self.form.data = }")
# previous = dict(self.record)
logging.debug(f"{self.record = }")
self.populate()
# transaction_log.record(previous, self.record)
2024-02-04 15:22:54 -08:00
with db.transaction():
db.add(self.record)
self.save_callback()
logging.debug(f"Saved {self.record = }")
2024-02-08 23:26:19 -08:00
location = self.request.current_route_path()
if self.record.slug not in location:
2024-02-08 23:26:19 -08:00
location = f"{location}/{self.record.uri}"
logging.debug(f"Redirecting to {location}")
2024-02-04 15:22:54 -08:00
return HTTPFound(location=location)
def delete(self):
if not self.record.id:
return
with db.transaction():
db.query(self.model).filter_by(id=self.record.id).delete()
location = self.request.current_route_path()
return HTTPFound(location=location)
2024-01-31 22:39:54 -08:00
def response(self):
2024-02-04 15:22:54 -08:00
if not self.form:
2024-02-04 11:40:30 -08:00
return
2024-02-04 15:22:54 -08:00
elif self.form.save.data:
return self.save()
elif self.form.delete.data:
return self.delete()