Commit 1bb04b45 authored by axiiom's avatar axiiom

moved database models into a separate file, if not okay revert

parent 017fb798
from contextlib import contextmanager
from sqlalchemy import Column, Integer, String, Float, JSON, ForeignKey, Enum
from sqlalchemy.ext.declarative import as_declarative
from sqlalchemy.orm import relationship, validates
from .meta import Session
from .field_types import FieldType
from .meta import Session, engine
from .models import Base, Point, Category, Field
@contextmanager
......@@ -36,112 +33,3 @@ def with_session(func):
# Flask identifies endpoint handlers based on their name
wrapper.__name__ = func.__name__
return wrapper
@as_declarative()
class Base(object):
pass
class Point(Base):
"""
Represents actual instances of any and all points on the map.
"""
__tablename__ = 'point'
id = Column(Integer, primary_key=True, autoincrement=True)
name = Column(String, nullable=True)
lat = Column(Float, nullable=False)
lon = Column(Float, nullable=False)
attributes = Column(JSON, nullable=False)
# Relationships
category_id = Column(Integer, ForeignKey('category.id'), nullable=False)
category = relationship('Category')
parent_id = Column(Integer, ForeignKey('point.id'), nullable=True)
parent = relationship('Point', remote_side=[id])
children = relationship('Point')
def __init__(self, **kwargs):
# Need to load category first or else attribute validation will fail
if 'category' in kwargs:
self.category = kwargs.pop('category')
super(Point, self).__init__(**kwargs)
@validates('attributes')
def validate_data(self, _, data):
if data is None:
return
fields = self.category.fields
for key in data:
# Find Field object that corresponds to this key
for field in fields:
if field.slug == key:
break
else:
raise ValueError(f'extra data "{key}" must be a registered field')
field.validate_data(data[key])
return data
def as_json(self, children=True):
if children:
children = [child.as_json(children=False) for child in self.children]
return {
"name": self.name,
"lat": self.lat,
"lon": self.lon,
"category": self.category.id,
"attributes": self.attributes,
"children": children
}
class Category(Base):
"""
Represent a schema for a single category of objects (e.g. water fountain or bathroom)
"""
__tablename__ = 'category'
id = Column(Integer, primary_key=True, autoincrement=True)
name = Column(String, nullable=False, unique=True)
icon = Column(String, nullable=True)
fields = relationship("Field")
def as_json(self):
return {
"id": self.id,
"name": self.name,
"icon": self.icon,
"attributes": {attr.slug: attr.as_json() for attr in self.fields}
}
class Field(Base):
"""
Represents a single field in the Category schema.
"""
__tablename__ = 'field'
id = Column(Integer, primary_key=True, autoincrement=True)
slug = Column(String, nullable=False)
name = Column(String, nullable=False)
type = Column(Enum(FieldType), nullable=False)
# Relationship
category_id = Column(Integer, ForeignKey('category.id'))
def validate_data(self, data):
"""
Verify that data is the correct type for this Field.
"""
self.type.validate(data)
def as_json(self):
return {
"slug": self.slug,
"name": self.name,
"type": self.type.name
}
from sqlalchemy.ext.declarative import as_declarative
from sqlalchemy import Column, Integer, String, Float, JSON, ForeignKey, Enum
from sqlalchemy.orm import relationship, validates
from . import FieldType
@as_declarative()
class Base(object):
pass
class Point(Base):
"""
Represents actual instances of any and all points on the map.
"""
__tablename__ = 'point'
id = Column(Integer, primary_key=True, autoincrement=True)
name = Column(String, nullable=True)
lat = Column(Float, nullable=False)
lon = Column(Float, nullable=False)
attributes = Column(JSON, nullable=False)
# Relationships
category_id = Column(Integer, ForeignKey('category.id'), nullable=False)
category = relationship('Category')
parent_id = Column(Integer, ForeignKey('point.id'), nullable=True)
parent = relationship('Point', remote_side=[id])
children = relationship('Point')
def __init__(self, **kwargs):
# Need to load category first or else attribute validation will fail
if 'category' in kwargs:
self.category = kwargs.pop('category')
super(Point, self).__init__(**kwargs)
@validates('attributes')
def validate_data(self, _, data):
if data is None:
return
fields = self.category.fields
for key in data:
# Find Field object that corresponds to this key
for field in fields:
if field.slug == key:
break
else:
raise ValueError(f'extra data "{key}" must be a registered field')
field.validate_data(data[key])
return data
def as_json(self, children=True):
if children:
children = [child.as_json(children=False) for child in self.children]
return {
"name": self.name,
"lat": self.lat,
"lon": self.lon,
"category": self.category.id,
"attributes": self.attributes,
"children": children
}
class Category(Base):
"""
Represent a schema for a single category of objects (e.g. water fountain or bathroom)
"""
__tablename__ = 'category'
id = Column(Integer, primary_key=True, autoincrement=True)
name = Column(String, nullable=False, unique=True)
icon = Column(String, nullable=True)
fields = relationship("Field")
def as_json(self):
return {
"id": self.id,
"name": self.name,
"icon": self.icon,
"attributes": {attr.slug: attr.as_json() for attr in self.fields}
}
class Field(Base):
"""
Represents a single field in the Category schema.
"""
__tablename__ = 'field'
id = Column(Integer, primary_key=True, autoincrement=True)
slug = Column(String, nullable=False)
name = Column(String, nullable=False)
type = Column(Enum(FieldType), nullable=False)
# Relationship
category_id = Column(Integer, ForeignKey('category.id'))
def validate_data(self, data):
"""
Verify that data is the correct type for this Field.
"""
self.type.validate(data)
def as_json(self):
return {
"slug": self.slug,
"name": self.name,
"type": self.type.name
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment