112 lines
3.5 KiB
Python
112 lines
3.5 KiB
Python
"""
|
|
Define an Abstract Base Class (ABC) for models
|
|
"""
|
|
from datetime import datetime
|
|
from decimal import Decimal
|
|
from sqlalchemy import inspect
|
|
from sqlalchemy.sql.expression import and_
|
|
from sqlalchemy.orm.collections import InstrumentedList
|
|
|
|
from pyjeeves import logging
|
|
|
|
from . import db
|
|
|
|
logger = logging.getLogger("PyJeeves." + __name__)
|
|
|
|
|
|
class RawBaseModel():
|
|
""" Generalize __init__, __repr__ and to_json
|
|
Based on the models columns , ForetagKod=1"""
|
|
|
|
print_only = () # First filter
|
|
print_filter = () # Second filter
|
|
to_json_filter = () # Only json filter
|
|
column_map = {}
|
|
|
|
__table_args__ = {
|
|
'extend_existing': True
|
|
}
|
|
|
|
@classmethod
|
|
def _base_filters(self, obj, filters=and_()):
|
|
# This method provides base filtering, additional filtering can be done in subclasses
|
|
# Add this method to your model if you want more filtering, otherwise leave it out
|
|
# import and_ from sqlalchemy package
|
|
# this is a base filter for ALL queries
|
|
return and_(
|
|
obj.ForetagKod == 1,
|
|
filters
|
|
)
|
|
|
|
def __repr__(self):
|
|
""" Define a base way to print models
|
|
Columns inside `print_filter` are excluded """
|
|
return '%s(%s)' % (self.__class__.__name__, {
|
|
column: value
|
|
for column, value in self._to_dict().items()
|
|
if column not in self.print_filter
|
|
})
|
|
|
|
@staticmethod
|
|
def _to_json_types(value):
|
|
if isinstance(value, datetime):
|
|
return value.strftime('%Y-%m-%d')
|
|
if isinstance(value, Decimal):
|
|
return "%.2f" % value
|
|
try:
|
|
if isinstance(value, InstrumentedList):
|
|
return [x.json for x in value]
|
|
if type(value).__module__ != 'builtins': # Perhaps == builtin?
|
|
return value.json
|
|
except AttributeError:
|
|
logger.debug(str(type(value)) + " was not converted to jsonifyable type")
|
|
return None
|
|
|
|
return value
|
|
|
|
@property
|
|
def json(self):
|
|
""" Define a base way to jsonify models
|
|
Columns inside `to_json_filter` are excluded
|
|
Columns inside `to_json_only_filter` are only included """
|
|
return {
|
|
column: RawBaseModel._to_json_types(value)
|
|
# if not isinstance(value, datetime) else value.strftime('%Y-%m-%d')
|
|
# if type(value).__module__ != self.__module__ # Perhaps == builtin?
|
|
# else value.json # Convert instances to json if same module
|
|
for column, value in self._to_dict().items()
|
|
if column not in self.to_json_filter
|
|
}
|
|
|
|
def _to_dict(self):
|
|
""" This would more or less be the same as a `to_json`
|
|
But putting it in a "private" function
|
|
Allows to_json to be overriden without impacting __repr__
|
|
Or the other way around
|
|
And to add filter lists """
|
|
return {
|
|
self._map_columns(column.key): getattr(self, column.key)
|
|
for column in inspect(self.__class__).attrs
|
|
if not self.print_only or column.key in self.print_only
|
|
}
|
|
|
|
def _map_columns(self, key):
|
|
if key in self.column_map:
|
|
return self.column_map[key]
|
|
return key
|
|
|
|
def merge(self):
|
|
db.raw_session.merge(self)
|
|
return self
|
|
|
|
def commit(self):
|
|
db.raw_session.commit()
|
|
|
|
def save(self):
|
|
db.raw_session.add(self)
|
|
db.raw_session.commit()
|
|
return self
|
|
|
|
def delete(self):
|
|
db.raw_session.delete(self)
|
|
db.raw_session.commit()
|