class RichTextContentBlock(SurrogatePK, Slugged, TimeStamped, Confirmable, Model): __tablename__ = 'rich_text_content_block' content = Column(db.Text(), nullable=False, default='') __table_args__ = (db.UniqueConstraint('slug', name='_rtcb_slug_uc'), db.Index('_rtcb_slug_active_ix', 'slug', 'active')) def __repr__(self): return self.title @classmethod def default_content(cls): ret = {} title = 'About text (left column)' slug = slugify(title, to_lower=True) ret[slug] = cls( title=title, slug=slug, content=('<p>The aim of this app is to demonstrate that, with the ' 'help of modern JS libraries, and with some well-' 'thought-out server-side snippets, it\'s now perfectly ' 'possible to "bake in" live in-place editing for ' 'virtually every content element in a typical ' 'brochureware site.</p>'), active=True) title = 'About text (right column)' slug = slugify(title, to_lower=True) ret[slug] = cls( title=title, slug=slug, content=('<p>This app is not a CMS. On the contrary, think of it ' 'as a proof-of-concept alternative to a CMS. An ' 'alternative where there\'s no "admin area", there\'s ' 'no "editing mode", and there\'s no "preview ' 'button".</p>'), active=True) title = 'About text (below columns)' slug = slugify(title, to_lower=True) ret[slug] = cls(title=title, slug=slug, content="<p>There's only direct manipulation.</p>", active=True) return ret
class ImageContentBlock(SurrogatePK, Slugged, TimeStamped, Confirmable, Model): __tablename__ = 'image_content_block' image = Column(db.String(255), nullable=False, default='') __table_args__ = (db.UniqueConstraint('slug', name='_icb_slug_uc'), db.Index('_icb_slug_active_ix', 'slug', 'active')) def __repr__(self): return self.title @property def image_path(self): return (self.image and '%s%s' % (app.config['UPLOADS_RELATIVE_PATH'], self.image) or None) @property def image_url(self): if not self.image: return None return url_for('static', filename=self.image_path, _external=True) @property def image_or_placeholder(self): return (self.image or app.config['EDITABLE_PLACEHOLDER_IMAGE_RELATIVE_PATH']) @classmethod def default_content(cls): ret = {} title = 'Site logo' slug = slugify(title, to_lower=True) ret[slug] = cls( title=title, slug=slug, image=app.config['EDITABLE_PLACEHOLDER_IMAGE_RELATIVE_PATH'], active=True) return ret
class Event(SurrogatePK, Slugged, TimeStamped, Confirmable, Model): __tablename__ = 'event' start_date = Column(db.Date(), nullable=False) end_date = Column(db.Date()) start_time = Column(db.Time()) end_time = Column(db.Time()) event_url = Column(db.String(255), nullable=False, default='') location_name = Column(db.String(255), nullable=False, default='') location_url = Column(db.String(255), nullable=False, default='') __table_args__ = (db.UniqueConstraint('slug', name='_event_slug_uc'), db.Index('_event_active_startdate_ix', 'active', 'start_date')) def __repr__(self): return self.title @classmethod def new_item(cls, title_prefix='New ', rand_start_date=False): rand_str = ''.join( random.choice(string.ascii_lowercase) for _ in range(10)) title = '{0}Event {1}'.format(title_prefix, rand_str) slug = slugify(title, to_lower=True) # Make start date a random date within 5 years of today date_now = date.today() start_date = date_now if rand_start_date: fiveyears_indays = 365 * 5 rand_delta = timedelta( days=random.randrange(-fiveyears_indays, fiveyears_indays)) start_date += rand_delta start_time = None # Toss a coin to see if we set a start time or not if bool(random.getrandbits(1)): rand_delta = timedelta(minutes=(15 * random.randrange(96))) dt_now = datetime.now() dt_midnighttoday = datetime(dt_now.year, dt_now.month, dt_now.day) start_time = (dt_midnighttoday + rand_delta).time() end_date = None end_time = None # Toss a coin to see if we set an end date or not if bool(random.getrandbits(1)): # Make end date 5 days or less ahead of start date rand_delta = timedelta(days=random.randrange(1, 6)) end_date = start_date + rand_delta # Toss a coin to see if we set an end time or not if bool(random.getrandbits(1)): rand_delta = timedelta(minutes=(15 * random.randrange(96))) dt_now = datetime.now() dt_midnighttoday = datetime(dt_now.year, dt_now.month, dt_now.day) end_time = (dt_midnighttoday + rand_delta).time() # Toss a coin to see if we set an event URL or not event_url = '' if bool(random.getrandbits(1)): event_url = random.choice(app.config['EDITABLE_SAMPLE_URLS']) # Toss a coin to see if we set a location name or not location_name = '' location_url = '' if bool(random.getrandbits(1)): rand_str = ''.join( random.choice(string.ascii_lowercase) for _ in range(10)) location_name = 'Location {0}'.format(rand_str) # Toss a coin to see if we set a location URL or not if bool(random.getrandbits(1)): location_url = random.choice( app.config['EDITABLE_SAMPLE_URLS']) return cls(title=title, slug=slug, start_date=start_date, end_date=end_date, start_time=start_time, end_time=end_time, event_url=event_url, location_name=location_name, location_url=location_url, active=True) @classmethod def default_content(cls): return [ cls.new_item(title_prefix='Sample ', rand_start_date=True) for i in range(app.config['EVENT_NUM_DEFAULT_ITEMS']) ]
class GalleryItem(SurrogatePK, Slugged, TimeStamped, Confirmable, Model): __tablename__ = 'gallery_item' image = Column(db.String(255), nullable=False, default='') content = Column(db.Text(), nullable=False, default='') date_taken = Column(db.String(255), nullable=False, default='') weight = db.Column(db.Integer(), nullable=False, default=0) __table_args__ = ( db.UniqueConstraint('slug', name='_gi_slug_uc'), db.Index('_gi_slug_active_ix', 'slug', 'active')) def __repr__(self): return self.title @property def image_path(self): return ( self.image and '%s%s' % ( app.config['UPLOADS_RELATIVE_PATH'], self.image) or None) @property def image_url(self): if not self.image: return None return url_for('static', filename=self.image_path, _external=True) @property def image_or_placeholder(self): return ( self.image or app.config['EDITABLE_PLACEHOLDER_IMAGE_RELATIVE_PATH']) @classmethod def new_item(cls, title_prefix='New '): rand_str = ''.join( random.choice(string.ascii_lowercase) for _ in range(10)) title = '{0}Gallery Item {1}'.format(title_prefix, rand_str) slug = slugify(title, to_lower=True) year_now = date.today().year date_taken = '{0} {1}'.format( random.choice(['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']), random.choice([(year_now - x) for x in range(1, 11)])) return cls( title=title, slug=slug, image=app.config[ 'EDITABLE_PLACEHOLDER_IMAGE_RELATIVE_PATH'], date_taken=date_taken, content=app.config['EDITABLE_PLACEHOLDER_TEXT'], active=True) @classmethod def default_content(cls): ret = [] for i in range(app.config['GALLERY_NUM_DEFAULT_ITEMS']): item = cls.new_item(title_prefix='Sample ') item.weight = i ret.append(item) return ret @classmethod def max_weight(cls): result = (cls.query .with_entities( func.max(cls.weight).label('max_weight')) .first()) if not ( result and (type(result).__name__ in ('KeyedTuple', 'result')) and len(result) and result[0] is not None): return None return int(result[0])
class ShortTextContentBlock(SurrogatePK, Slugged, TimeStamped, Confirmable, Model): __tablename__ = 'short_text_content_block' content = Column(db.String(255), nullable=False, default='') __table_args__ = (db.UniqueConstraint('slug', name='_stcb_slug_uc'), db.Index('_stcb_slug_active_ix', 'slug', 'active')) def __repr__(self): return self.title @classmethod def default_content(cls): ret = {} title = 'Site welcome prefix' slug = slugify(title, to_lower=True) ret[slug] = cls(title=title, slug=slug, content='Welcome to', active=True) title = 'Site byline' slug = slugify(title, to_lower=True) ret[slug] = cls( title=title, slug=slug, content=('A template for building a small marketing web site ' 'in Flask where all content is live editable.'), active=True) title = 'Site byline link title' slug = slugify(title, to_lower=True) ret[slug] = cls(title=title, slug=slug, content='Learn more', active=True) title = 'Site byline link URL' slug = slugify(title, to_lower=True) ret[slug] = cls(title=title, slug=slug, content='https://github.com/Jaza/flask-editablesite', active=True) title = 'About title' slug = slugify(title, to_lower=True) ret[slug] = cls(title=title, slug=slug, content='About', active=True) title = 'Gallery title' slug = slugify(title, to_lower=True) ret[slug] = cls(title=title, slug=slug, content='Gallery', active=True) title = 'Events title' slug = slugify(title, to_lower=True) ret[slug] = cls(title=title, slug=slug, content='Events', active=True) title = 'Contact title' slug = slugify(title, to_lower=True) ret[slug] = cls(title=title, slug=slug, content='Contact', active=True) return ret