class Property(BaseMixin, db.Model): __tablename__ = 'property' node_id = db.Column(None, db.ForeignKey('node.id'), nullable=False) name = db.Column(db.Unicode(40), nullable=False) value = db.Column(db.Unicode(250), nullable=False) __table_args__ = (db.UniqueConstraint('name', 'node_id'), )
class File(BaseScopedNameMixin, db.Model): __tablename__ = 'file' file_folder_id = db.Column(None, db.ForeignKey('file_folder.id'), nullable=False) file_folder = db.relationship(FileFolder) parent = db.synonym('file_folder') url = db.Column(db.Unicode(250), nullable=False) __table_args__ = (db.UniqueConstraint('file_folder_id', 'name'))
class Folder(BaseScopedNameMixin, db.Model): __tablename__ = 'folder' #: Website this folder is under website_id = db.Column(db.Integer, db.ForeignKey('website.id'), nullable=False) _theme = db.Column("theme", db.Unicode(80), nullable=False, default=u'') website = db.relationship(Website, backref=db.backref('folders', order_by='Folder.name', cascade='all, delete-orphan')) parent = db.synonym('website') __table_args__ = (db.UniqueConstraint('name', 'website_id'), ) @property def theme(self): return self._theme or self.website.theme @theme.setter def theme(self, value): self._theme = value #: Theme used by the folder. Defaults to the website's theme. theme = db.synonym('_theme', descriptor=theme) def __init__(self, **kwargs): super(Folder, self).__init__(**kwargs) #index = Page(name=u'', title=u'Index', folder=self, template=u'page.html') #index.name = u'' # Reset it to a blank #self.pages.append(index) def __repr__(self): return u'<Folder %s at %s>' % (self.name or '(root)', self.website.name) def url_for(self, action='view'): """ Returns a view URL based on the website's URL field. """ if action == 'view': return urljoin(self.website.url, self.name) elif action == 'list': if self.name == u'': return url_for('website', website=self.website.name) else: return url_for('folder', website=self.website.name, folder=self.name) elif action == 'edit': if self.name != u'': return url_for('folder_edit', website=self.website.name, folder=self.name)
class EventAttendee(BaseMixin, db.Model): __tablename__ = 'event_attendee' # User who is attending user_id = db.Column(None, db.ForeignKey('user.id'), nullable=False) user = db.relationship(User) # Event that the user is attending event_id = db.Column(None, db.ForeignKey('event.id'), nullable=False) event = db.relationship(Event, backref=db.backref('attendees', cascade='all, delete-orphan')) # Status codes: U/known, Y/es, N/o, M/aybe, W/ait-listed status = db.Column(db.Unicode(1), nullable=False, default=u'U') __table_args__ = (db.UniqueConstraint('user_id', 'event_id'), )
class Node(BaseScopedNameMixin, db.Model): __tablename__ = 'node' #: Id of the node across sites (staging, production, etc) for import/export uuid = db.Column(db.Unicode(22), unique=True, default=newid, nullable=False) #: User who made this node user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False, default=default_user_id) user = db.relationship(User) #: Folder in which this node is located folder_id = db.Column(db.Integer, db.ForeignKey('folder.id'), nullable=False) folder = db.relationship(Folder, backref=db.backref('nodes', order_by='Node.name', cascade='all, delete-orphan')) parent = db.synonym('folder') #: Publication date published_at = db.Column(db.DateTime, default=datetime.utcnow, nullable=False) #: Type of node, for polymorphic identity type = db.Column('type', db.Unicode(20)) __table_args__ = (db.UniqueConstraint('name', 'folder_id'), ) __mapper_args__ = {'polymorphic_on': type} node_properties = db.relationship( Property, cascade='all, delete-orphan', collection_class=attribute_mapped_collection('name'), backref='node') @property def properties(self): if not hasattr(self, '_cached_properties'): self._cached_properties = _NodeProperties(self.node_properties, node=self) return self._cached_properties @properties.setter def properties(self, value): if not isinstance(value, dict): raise ValueError("Value is not a dictionary") for key in list(self.node_properties.keys()): if key not in value: self.node_properties.pop(key) self._cached_properties = _NodeProperties(value, node=self) def as_json(self): return { 'uuid': self.uuid, 'name': self.name, 'title': self.title, 'created_at': self.created_at.isoformat() + 'Z', 'updated_at': self.updated_at.isoformat() + 'Z', 'published_at': self.published_at.isoformat() + 'Z', 'userid': self.user.userid, 'type': self.type, 'properties': self.properties, } def import_from(self, data): self.uuid = data['uuid'] self.name = data['name'] self.title = data['title'] self.published_at = parse_isoformat(data['published_at']) self.properties = data['properties'] def import_from_internal(self, data): # Only required for nodes that keep internal references to other nodes pass def url_for(self, action='view'): """ Return a URL to this node. """ if action == 'view': if self.folder.name == u'': return url_for('folder', folder=self.name) else: return url_for('node', folder=self.folder.name, node=self.name) elif action == 'edit': return url_for('node_edit', website=self.folder.website.name, folder=self.folder.name, node=self.name) elif action == 'delete': return url_for('node_delete', website=self.folder.website.name, folder=self.folder.name, node=self.name)