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
|
|
|
from sqlalchemy.inspection import inspect
|
|
|
|
|
|
|
|
from ttfrog.attribute_map import AttributeMap
|
2024-01-31 22:39:54 -08:00
|
|
|
from ttfrog.db.manager import db
|
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-02-04 11:40:30 -08:00
|
|
|
def query_factory(model):
|
|
|
|
return lambda: db.query(model).all()
|
|
|
|
|
|
|
|
|
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
|
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)
|
|
|
|
return self._form
|
2024-02-01 00:28:17 -08:00
|
|
|
|
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 coerce_foreign_keys(self):
|
|
|
|
inspector = inspect(db.engine)
|
|
|
|
foreign_keys = inspector.get_foreign_keys(table_name=self.record.__class__.__tablename__)
|
|
|
|
for foreign_key in foreign_keys:
|
|
|
|
for col in inspector.get_columns(foreign_key['referred_table']):
|
|
|
|
if col['name'] == foreign_key['referred_columns'][0]:
|
|
|
|
col_name = foreign_key['constrained_columns'][0]
|
|
|
|
col_type = col['type'].python_type
|
|
|
|
col_value = col_type(getattr(self.record, col_name))
|
|
|
|
setattr(self.record, col_name, col_value)
|
|
|
|
|
|
|
|
def template_context(self, **kwargs) -> dict:
|
|
|
|
return AttributeMap.from_dict({
|
|
|
|
'c': dict(
|
|
|
|
config=self.config,
|
|
|
|
request=self.request,
|
|
|
|
form=self.form,
|
|
|
|
record=self.record,
|
|
|
|
routes=get_all_routes(self.request),
|
|
|
|
**self.attrs,
|
|
|
|
**kwargs,
|
|
|
|
)
|
|
|
|
})
|
2024-01-31 22:39:54 -08:00
|
|
|
|
2024-02-04 15:22:54 -08:00
|
|
|
def save(self):
|
|
|
|
if not self.form.save.data:
|
|
|
|
return
|
|
|
|
if not self.form.validate():
|
|
|
|
return
|
|
|
|
self.form.populate_obj(self.record)
|
|
|
|
self.coerce_foreign_keys()
|
|
|
|
if self.record.id:
|
|
|
|
return
|
|
|
|
with db.transaction():
|
|
|
|
db.add(self.record)
|
|
|
|
logging.debug(f"Added {self.record = }")
|
|
|
|
location = f"{self.request.current_route_path()}/{self.record.uri}"
|
|
|
|
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()
|
|
|
|
logging.debug(f"Deleted {self.record = }")
|
|
|
|
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()
|