예제 #1
0
파일: helpers.py 프로젝트: ra2003/oy-cms
def _prepare_association_table(table_name, remote1, remote2):
    return db.Table(
        table_name,
        db.metadata,
        db.Column(f"{remote1}_id", db.Integer, db.ForeignKey(f"{remote1}.id")),
        db.Column(f"{remote2}_id", db.Integer, db.ForeignKey(f"{remote2}.id")),
    )
예제 #2
0
 def category_id(cls):
     if not hasattr(cls, "Category"):
         category_attrs = {
             "id": db.Column(db.Integer, primary_key=True),
             "objects": db.relationship(cls, backref="category"),
         }
         cls.Category = type(f"{cls.__name__}Category",
                             (ClassifierMixin, db.Model), category_attrs)
     return db.Column(db.Integer, db.ForeignKey(cls.Category.id))
예제 #3
0
파일: metadata.py 프로젝트: ra2003/oy-cms
class Metadata(SQLAEvent):
    """Provides metadata about a specific piece of content."""

    meta_title = db.Column(
        db.Unicode(255),
        default="",
        info=dict(label="Meta Title",
                  description="The title used by search engines"),
    )
    meta_description = db.Column(
        db.UnicodeText,
        default="",
        info=dict(
            label="Meta Description",
            description="The description used by search engines",
        ),
    )
    keywords = db.Column(
        db.Text,
        default="",
        info=dict(
            label="Keywords",
            description=
            "The keywords for this content (Used by search engines)",
        ),
    )
    should_auto_generate = db.Column(
        db.Boolean,
        info=dict(
            label="Auto generate the metadata",
            description="If enabled the metadata will be generated automaticly",
        ),
    )

    def __get_meta_title__(self):
        return ""

    def __get_meta_description__(self):
        return ""

    def __get_keywords__(self):
        return ""

    def before_flush(self, session, is_modified):
        if self.should_auto_generate is None:
            self.should_auto_generate = True
        if not self.should_auto_generate:
            return
        cols = ["keywords", "meta_title", "meta_description"]
        state = db.inspect(self)
        for col in cols:
            state = db.inspect(self)
            if state.attrs[col].history.unchanged:
                continue
            func = getattr(self, f"__get_{col}__", None)
            if callable(func):
                setattr(self, col, func())
예제 #4
0
파일: settings.py 프로젝트: ra2003/oy-cms
class Setting(DynamicProp, db.Model):
    __tablename__ = "setting"
    id = db.Column(db.Integer, primary_key=True)
    parent_id = db.Column(db.Integer, db.ForeignKey("settings.id"))
    category_id = db.Column(db.Integer, db.ForeignKey("setting_category.id"))
    cat = relationship("SettingCategory", backref="settings")

    category = association_proxy(
        "cat", "name", creator=lambda n: SettingCategory.get_or_create(name=n))

    def __repr__(self):
        return "<Setting key={}><category:{}>".format(self.key, self.category)
예제 #5
0
class TimeStampped(SQLAEvent):
    """Add created and updated fields"""

    created = db.Column(
        db.DateTime,
        default=datetime.utcnow,
        nullable=False,
        info=dict(label="Creation Date"),
    )
    updated = db.Column(db.DateTime, nullable=True, default=datetime.utcnow)

    def before_update(self, mapper, connection):
        if _request_ctx_stack.top is not None:
            self.updated = datetime.utcnow()
예제 #6
0
 def tags(cls):
     if not hasattr(cls, "Tag"):
         # Create the Tag model
         tag_attrs = {
             "id":
             db.Column(db.Integer, primary_key=True),
             "objects":
             db.relationship(
                 cls,
                 secondary=lambda: cls.__tags_association_table__,
                 backref="related_tags",
             ),
         }
         cls.Tag = type(f"{cls.__name__}Tag", (ClassifierMixin, db.Model),
                        tag_attrs)
         # The many-to-many association table
         cls.__tags_association_table__ = _prepare_association_table(
             table_name=f"{cls.__tablename__}s_tags",
             remote1=cls.__tablename__,
             remote2=cls.Tag.__tablename__,
         )
     return association_proxy(
         "related_tags",
         "title",
         creator=lambda t: cls.Tag.get_or_create(title=t))
예제 #7
0
 def editor_id(cls):
     return db.Column(
         db.Integer,
         db.ForeignKey("user.id"),
         nullable=True,
         info=dict(label=lazy_gettext("Author")),
     )
예제 #8
0
class Page(AbstractPage):
    """The concrete Page model."""

    __contenttype__ = "page"
    id = db.Column(db.Integer,
                   db.Sequence("page_id_seq", start=1, increment=1),
                   primary_key=True)
    query_class = PageQuery
예제 #9
0
 def show_in_menu(cls):
     return db.Column(
         db.Boolean,
         default=True,
         info=dict(
             label="Show in menu",
             description="Show this page in the navigation menus.",
         ),
     )
예제 #10
0
class CommentMixin(SelfRelated):
    author_name = db.Column(db.String(255), nullable=False)
    author_email = db.Column(db.String(255), nullable=False)
    body = db.Column(db.Text)
    remote_addr = db.Column(
        db.String(255), nullable=False, default=lambda: request.remote_addr
    )
    user_agent = db.Column(
        db.String(255), nullable=False, default=lambda: request.user_agent
    )

    def __init__(self, author_name, author_email, body):
        self.author_name = author_name
        self.body = body
        if email(author_email):
            self.author_email = author_email
        else:
            raise ValueError(f"{author_email} is not a valid email address.")
예제 #11
0
파일: slugged.py 프로젝트: ra2003/oy-cms
 def slug(cls):
     return db.Column(
         db.Unicode(255),
         info=dict(
             label="Slug",
             description=
             "A Slug is that portion of the URL used to identify this content.",
         ),
     )
예제 #12
0
파일: misc.py 프로젝트: ra2003/oy-cms
class Ordered(SQLAEvent):
    """Provide an ordering field."""

    sort_order = db.Column(db.Integer)
    __children_ordering_column__ = "sort_order"

    def after_flush_postexec(self, session, is_modified):
        if self.sort_order is None:
            self.sort_order = db.inspect(self).mapper.primary_key[0]
예제 #13
0
파일: settings.py 프로젝트: ra2003/oy-cms
class Settings(ImmutableProxiedDictMixin, db.Model, SQLAEvent):
    id = db.Column(db.Integer, primary_key=True)
    store = db.relationship(
        "Setting", collection_class=attribute_mapped_collection("key"))
    _proxied = association_proxy("store", "value")
    profile_id = db.Column(db.Integer,
                           db.ForeignKey("settings_profile.id"),
                           nullable=False)

    def on_init(self):
        process_func = lambda seq: [Field(**d) for d in seq if type(d) is dict]
        ready = ((c, process_func(l))
                 for c, l in current_app.provided_settings)
        for category, opts in ready:
            for opt in opts:
                setting = Setting(key=opt.name)
                setting.value = opt.default
                setting.category = str(category)
                db.session.add(setting)
                self.store[opt.name] = setting
예제 #14
0
파일: slugged.py 프로젝트: ra2003/oy-cms
class Titled(SQLAEvent):
    """Provide a mandatory title field"""

    title = db.Column(
        db.Unicode(512),
        nullable=False,
        info=dict(label="Title",
                  description="The title to display for the end user."),
    )

    def __str__(self):
        return self.title
예제 #15
0
파일: settings.py 프로젝트: ra2003/oy-cms
class SettingsProfile(SQLAEvent, db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(
        db.Unicode(255),
        unique=True,
        nullable=False,
        info=dict(
            label="Profile Name:",
            description="A Unique name for this settings profile.",
        ),
    )
    is_active = db.Column(
        db.Boolean,
        default=False,
        info=dict(
            label="Active",
            description=
            "Sets or unsets this settings profile as the default profile",
        ),
    )
    settings = db.relationship("Settings", backref="profile", uselist=False)

    def on_init(self):
        if self.settings is None:
            self.settings = Settings()

    def after_flush_postexec(self, session, is_modified):
        if self.is_active:
            thistbl = get_owning_table(self, "is_active")
            up = (db.update(thistbl).where(
                db.and_(thistbl.c.id != self.id,
                        thistbl.c.is_active == True)).values(is_active=False))
            db.session.execute(up)

    def __str__(self):
        return self.name

    def __repr__(self):
        return "SettingsProfile(name='{}')".format(self.name)
예제 #16
0
파일: models.py 프로젝트: ra2003/oy-cms
class Profile(ImmutableProxiedDictMixin, db.Model, TimeStampped):
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(
        db.Integer,
        db.ForeignKey("user.id"),
        unique=True,
        nullable=False,
        info=dict(label=lazy_gettext("User")),
    )
    user = db.relationship(
        User,
        backref=backref("profile", uselist=False, cascade="all, delete-orphan"),
        single_parent=True,
        info=dict(label=lazy_gettext("User"), description=lazy_gettext("")),
    )
    extras = db.relationship(
        "ProfileExtras", collection_class=attribute_mapped_collection("key")
    )
    _proxied = association_proxy("extras", "value")

    def __repr__(self):
        return f"<{self.user.user_name}: Profile()>"
예제 #17
0
파일: user.py 프로젝트: ra2003/oy-cms
class User(db.Model, UserMixin, SQLAEvent):
    id = db.Column(db.Integer, primary_key=True)
    user_name = db.Column(
        db.Unicode(128),
        nullable=False,
        unique=True,
        index=True,
        info=dict(
            label=lazy_gettext("User Name"),
            description=lazy_gettext(
                "A unique name for this user (used for login)"),
        ),
    )
    email = db.Column(
        db.String(255),
        unique=True,
        info=dict(label=lazy_gettext("Email"), description=lazy_gettext("")),
    )
    password = db.Column(
        db.String(255),
        info=dict(label=lazy_gettext("Password"),
                  description=lazy_gettext("")),
    )
    active = db.Column(
        db.Boolean,
        info=dict(
            label=lazy_gettext("Active"),
            description=lazy_gettext(
                "Activate or deactivate this user account"),
        ),
    )
    confirmed_at = db.Column(db.DateTime(),
                             info=dict(label=lazy_gettext("Confirmed At")))
    roles = db.relationship(
        "Role",
        secondary=roles_users,
        backref=db.backref("users", lazy="dynamic"),
        info=dict(label=lazy_gettext("Roles"), description=lazy_gettext("")),
    )
    # TODO: remove this one
    name = property(fget=lambda self: self.profile.name)

    @validates("password")
    def validate_password(self, key, value):
        """TBD later"""
        return value

    @validates("email")
    def validate_email(self, key, value):
        if not is_valid_email(value):
            raise ValueError("Invalid email address for %r" % self)
        return value

    def __str__(self):
        return self.user_name

    def __repr__(self):
        return "User(user_name={})".format(self.user_name)
예제 #18
0
파일: user.py 프로젝트: ra2003/oy-cms
class Role(db.Model, RoleMixin):
    id = db.Column(db.Integer(), primary_key=True)
    name = db.Column(
        db.String(80),
        unique=True,
        info=dict(
            label=lazy_gettext("Name"),
            description=lazy_gettext("A name to identify this role"),
        ),
    )
    description = db.Column(
        db.Unicode(255),
        info=dict(
            label=lazy_gettext("Description"),
            description=lazy_gettext("A simple summary about this role."),
        ),
    )

    def __str__(self):
        return self.name

    def __repr__(self):
        return f"<Role(name='{self.name}'>"
예제 #19
0
 def comments(cls):
     if not hasattr(cls, "Comment"):
         comment_attrs = {"id": db.Column(db.Integer, primary_key=True)}
         cls.Comment = type(
             f"{cls.__name__}Comment", (CommentMixin, db.Model), comment_attrs
         )
         # The many-to-many association table
         cls.__comments_association_table__ = _prepare_association_table(
             table_name=f"{cls.__tablename__}s_comments",
             remote1=cls.__tablename__,
             remote2=cls.Comment.__tablename__,
         )
     return db.relationship(
         cls.Comment, secondary=cls.__comments_association_table__, backref="objects"
     )
예제 #20
0
class AbstractPage(NodeSpec, Displayable, BaseNestedSets,
                   ScopedUniquelySlugged):
    """Extends :class:`Displayable` with special fields"""

    __abstract__ = True

    url_path = db.Column(db.String(1024),
                         unique=True,
                         nullable=True,
                         index=True)

    @hybrid_property
    def url(self):
        return self.url_path

    @staticmethod
    def construct_url_path(page):
        slugs = [p.slug for p in page.path_to_root(order=db.asc)]
        return "/".join(slugs)

    def before_commit(self, session, is_modified):
        session.flush()
        state = db.inspect(self)
        tbl = state.mapper.primary_base_mapper.tables[0]
        rps = [self.slug]
        parent = self.parent
        while parent is not None:
            rps.append(parent.slug)
            parent = parent.parent
        rps.reverse()
        new_url_path = "/".join(rps)
        up = db.update(tbl).where(tbl.c.id == self.id).values(
            url_path=new_url_path)
        session.execute(up)
        session.refresh(self)
        with session.no_autoflush:
            for child in self.children:
                AbstractPage.before_commit(child, session, True)

    def __repr__(self):
        return f'<{self.__class__.__name__}(title="{self.title}")>'
예제 #21
0
파일: settings.py 프로젝트: ra2003/oy-cms
class SettingCategory(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), nullable=False, unique=True)

    def __init__(self, name):
        self.name = name
예제 #22
0
 def contenttype(cls):
     return db.Column(db.String(128), info=dict(label="Type"))
예제 #23
0
파일: models.py 프로젝트: ra2003/oy-cms
class ProfileExtras(DynamicProp, db.Model):
    id = db.Column(db.Integer, primary_key=True)
    profile_id = db.Column(db.Integer, db.ForeignKey("profile.id"))
예제 #24
0
파일: misc.py 프로젝트: ra2003/oy-cms
 def parent_id(cls):
     return db.Column(db.Integer, db.ForeignKey(cls.id), info=dict(label="Parent"))
예제 #25
0
class DynamicProp(PolymorphicVerticalProperty):
    key = db.Column(db.String(128), nullable=False)
    type = db.Column(db.String(64))
    int_value = db.Column(db.Integer, info={"type": (int, "integer")})
    str_value = db.Column(db.Unicode(5120), info={"type": (str, "string")})
    bool_value = db.Column(db.Boolean, info={"type": (bool, "boolean")})
예제 #26
0
파일: user.py 프로젝트: ra2003/oy-cms
    :license: MIT, see LICENSE for more details.
"""

from sqlalchemy import inspect
from sqlalchemy.orm import validates
from sqlalchemy.orm.collections import attribute_mapped_collection
from sqlalchemy.ext.associationproxy import association_proxy
from flask_security import UserMixin, RoleMixin
from oy.boot.sqla import db
from oy.babel import lazy_gettext
from oy.helpers import is_valid_email
from oy.models.mixins import TimeStampped, SQLAEvent

roles_users = db.Table(
    "roles_users",
    db.Column("user_id", db.Integer(), db.ForeignKey("user.id")),
    db.Column("role_id", db.Integer(), db.ForeignKey("role.id")),
)


class Role(db.Model, RoleMixin):
    id = db.Column(db.Integer(), primary_key=True)
    name = db.Column(
        db.String(80),
        unique=True,
        info=dict(
            label=lazy_gettext("Name"),
            description=lazy_gettext("A name to identify this role"),
        ),
    )
    description = db.Column(