コード例 #1
0
ファイル: models.py プロジェクト: wayne391/flask-shop
class Page(Model):
    __tablename__ = "public_page"
    title = Column(db.String(255), nullable=False)
    slug = Column(db.String(255))
    content = Column(db.Text())
    is_visible = Column(db.Boolean(), default=True)
    if Config.USE_REDIS:
        content = PropsItem("content", "")

    def get_absolute_url(self):
        identity = self.slug or self.id
        return url_for("public.show_page", identity=identity)

    @classmethod
    @cache(MC_KEY_PAGE_ID.format("{identity}"))
    def get_by_identity(cls, identity):
        try:
            int(identity)
        except ValueError:
            return Page.query.filter(Page.slug == identity).first()
        return Page.get_by_id(identity)

    @property
    def url(self):
        return self.get_absolute_url()

    def __str__(self):
        return self.title

    @classmethod
    def __flush_after_update_event__(cls, target):
        super().__flush_after_update_event__(target)
        rdb.delete(MC_KEY_PAGE_ID.format(target.id))
        rdb.delete(MC_KEY_PAGE_ID.format(target.slug))
コード例 #2
0
class PluginRegistry(Model):
    __tablename__ = "plugin_registry"
    name = Column(db.String(100), unique=True)
    enabled = Column(db.Boolean(), default=True)

    @property
    def info(self):
        return current_app.pluggy.plugin_metadata.get(self.name, {})
コード例 #3
0
ファイル: models.py プロジェクト: hi-trust/flask-shop
class OrderLine(Model):
    __tablename__ = "order_line"
    product_name = Column(db.String(255))
    product_sku = Column(db.String(100))
    quantity = Column(db.Integer())
    unit_price_net = Column(db.DECIMAL(10, 2))
    is_shipping_required = Column(db.Boolean(), default=True)
    order_id = Column(db.Integer())
    variant_id = Column(db.Integer())

    @property
    def variant(self):
        return ProductVariant.get_by_id(self.variant_id)

    def get_total(self):
        return self.unit_price_net * self.quantity
コード例 #4
0
class OrderNote(Model):
    __tablename__ = "order_note"
    order_id = Column(db.Integer())
    user_id = Column(db.Integer())
    content = Column(db.Text())
    is_public = Column(db.Boolean(), default=True)
コード例 #5
0
class ProductType(Model):
    __tablename__ = "product_type"
    title = Column(db.String(255), nullable=False)
    has_variants = Column(db.Boolean(), default=True)
    is_shipping_required = Column(db.Boolean(), default=False)

    def __str__(self):
        return self.title

    @property
    def product_attributes(self):
        at_ids = (ProductTypeAttributes.query.with_entities(
            ProductTypeAttributes.product_attribute_id).filter(
                ProductTypeAttributes.product_type_id == self.id).all())
        return ProductAttribute.query.filter(
            ProductAttribute.id.in_(id for id, in at_ids)).all()

    @property
    def variant_attributes(self):
        at_ids = (ProductTypeVariantAttributes.query.with_entities(
            ProductTypeVariantAttributes.product_attribute_id).filter(
                ProductTypeVariantAttributes.product_type_id == self.id).all())
        return ProductAttribute.query.filter(
            ProductAttribute.id.in_(id for id, in at_ids)).all()

    @property
    def variant_attr_id(self):
        if self.variant_attributes:
            return self.variant_attributes[0].id
        else:
            return None

    def update_product_attr(self, new_attrs):
        origin_ids = (ProductTypeAttributes.query.with_entities(
            ProductTypeAttributes.product_attribute_id).filter_by(
                product_type_id=self.id).all())
        origin_ids = set(i for i, in origin_ids)
        new_attrs = set(int(i) for i in new_attrs)
        need_del = origin_ids - new_attrs
        need_add = new_attrs - origin_ids
        for id in need_del:
            ProductTypeAttributes.query.filter_by(
                product_type_id=self.id,
                product_attribute_id=id).first().delete(commit=False)
        for id in need_add:
            new = ProductTypeAttributes(product_type_id=self.id,
                                        product_attribute_id=id)
            db.session.add(new)
        db.session.commit()

    def update_variant_attr(self, variant_attr):
        origin_attr = ProductTypeVariantAttributes.query.filter_by(
            product_type_id=self.id).first()
        if origin_attr:
            origin_attr.product_attribute_id = variant_attr
            origin_attr.save()
        else:
            ProductTypeVariantAttributes.create(
                product_type_id=self.id, product_attribute_id=variant_attr)

    def delete(self):
        need_del_product_attrs = ProductTypeAttributes.query.filter_by(
            product_type_id=self.id).all()
        need_del_variant_attrs = ProductTypeVariantAttributes.query.filter_by(
            product_type_id=self.id).all()

        for item in itertools.chain(need_del_product_attrs,
                                    need_del_variant_attrs):
            item.delete(commit=False)
        need_update_products = Product.query.filter_by(
            product_type_id=self.id).all()
        for product in need_update_products:
            product.product_type_id = 0
            db.session.add(product)
        db.session.delete(self)
        db.session.commit()
コード例 #6
0
class Product(Model):
    __tablename__ = "product_product"
    title = Column(db.String(255), nullable=False)
    on_sale = Column(db.Boolean(), default=True)
    rating = Column(db.DECIMAL(8, 2), default=5.0)
    sold_count = Column(db.Integer(), default=0)
    review_count = Column(db.Integer(), default=0)
    basic_price = Column(db.DECIMAL(10, 2))
    category_id = Column(db.Integer())
    is_featured = Column(db.Boolean(), default=False)
    product_type_id = Column(db.Integer())
    attributes = Column(MutableDict.as_mutable(db.JSON()))
    description = Column(db.Text())
    if Config.USE_REDIS:
        description = PropsItem("description")

    def __str__(self):
        return self.title

    def __iter__(self):
        return iter(self.variants)

    def get_absolute_url(self):
        return url_for("product.show", id=self.id)

    @property
    @cache(MC_KEY_PRODUCT_IMAGES.format("{self.id}"))
    def images(self):
        return ProductImage.query.filter(
            ProductImage.product_id == self.id).all()

    @property
    def first_img(self):
        if self.images:
            return str(self.images[0])
        return ""

    @property
    def is_in_stock(self):
        return any(variant.is_in_stock for variant in self)

    @property
    def category(self):
        return Category.get_by_id(self.category_id)

    @property
    def product_type(self):
        return ProductType.get_by_id(self.product_type_id)

    @property
    def is_discounted(self):
        if float(self.discounted_price) > 0:
            return True
        return False

    @property
    @cache(MC_KEY_PRODUCT_DISCOUNT_PRICE.format("{self.id}"))
    def discounted_price(self):
        from flaskshop.discount.models import Sale

        return Sale.get_discounted_price(self)

    @property
    def price(self):
        if self.is_discounted:
            return self.basic_price - self.discounted_price
        return self.basic_price

    @property
    def price_human(self):
        return "$" + str(self.price)

    @property
    def on_sale_human(self):
        return "Y" if self.on_sale else "N"

    @property
    @cache(MC_KEY_PRODUCT_VARIANT.format("{self.id}"))
    def variant(self):
        return ProductVariant.query.filter(
            ProductVariant.product_id == self.id).all()

    @property
    def attribute_map(self):
        items = {
            ProductAttribute.get_by_id(k): AttributeChoiceValue.get_by_id(v)
            for k, v in self.attributes.items()
        }
        return items

    @classmethod
    # @cache(MC_KEY_FEATURED_PRODUCTS.format("{num}"))
    def get_featured_product(cls, num=8):  # 首頁的 featured products
        return cls.query.filter_by(is_featured=True).limit(num).all()

    def update_images(self, new_images):
        origin_ids = (ProductImage.query.with_entities(
            ProductImage.product_id).filter_by(product_id=self.id).all())
        origin_ids = set(i for i, in origin_ids)
        new_images = set(int(i) for i in new_images)
        need_del = origin_ids - new_images
        need_add = new_images - origin_ids
        for id in need_del:
            ProductImage.get_by_id(id).delete(commit=False)
        for id in need_add:
            image = ProductImage.get_by_id(id)
            image.product_id = self.id
            image.save(commit=False)
        db.session.commit()

    def update_attributes(self, attr_values):
        attr_entries = [
            str(item.id) for item in self.product_type.product_attributes
        ]
        attributes = dict(zip(attr_entries, attr_values))
        self.attributes = attributes

    def generate_variants(self):
        if not self.product_type.has_variants:
            ProductVariant.create(sku=str(self.id) + "-1337",
                                  product_id=self.id)
        else:
            sku_id = 1337
            variant_attributes = self.product_type.variant_attributes[0]
            for value in variant_attributes.values:
                sku = str(self.id) + "-" + str(sku_id)
                attributes = {str(variant_attributes.id): str(value.id)}
                ProductVariant.create(
                    sku=sku,
                    title=value.title,
                    product_id=self.id,
                    attributes=attributes,
                )
                sku_id += 1

    def delete(self):
        need_del_collection_products = ProductCollection.query.filter_by(
            product_id=self.id).all()
        for item in itertools.chain(self.images, self.variant,
                                    need_del_collection_products):
            item.delete(commit=False)
        db.session.delete(self)
        db.session.commit()

    @staticmethod
    def clear_mc(target):
        rdb.delete(MC_KEY_PRODUCT_DISCOUNT_PRICE.format(target.id))
        keys = rdb.keys(MC_KEY_FEATURED_PRODUCTS.format("*"))
        for key in keys:
            rdb.delete(key)

    @staticmethod
    def clear_category_cache(target):
        keys = rdb.keys(
            MC_KEY_CATEGORY_PRODUCTS.format(target.category_id, "*"))
        for key in keys:
            rdb.delete(key)

    @classmethod
    def __flush_insert_event__(cls, target):
        super().__flush_insert_event__(target)

        if current_app.config["USE_ES"]:
            from flaskshop.public.search import Item

            Item.add(target)

    @classmethod
    def __flush_before_update_event__(cls, target):

        super().__flush_before_update_event__(target)
        target.clear_category_cache(target)

    @classmethod
    def __flush_after_update_event__(cls, target):

        super().__flush_after_update_event__(target)
        target.clear_mc(target)
        target.clear_category_cache(target)
        if current_app.config["USE_ES"]:
            from flaskshop.public.search import Item

            Item.update_item(target)

    @classmethod
    def __flush_delete_event__(cls, target):
        from flaskshop.public.search import Item

        super().__flush_delete_event__(target)
        target.clear_mc(target)
        target.clear_category_cache(target)
        Item.delete(target)
コード例 #7
0
class User(Model, UserMixin):
    __tablename__ = "account_user"
    username = Column(db.String(80), unique=True, nullable=False, comment="user`s name")
    email = Column(db.String(80), unique=True, nullable=False)
    #: The hashed password
    _password = Column("password", db.String(128))
    nick_name = Column(db.String(255))
    is_active = Column(db.Boolean(), default=False)
    open_id = Column(db.String(80), index=True)
    session_key = Column(db.String(80), index=True)

    def __init__(self, username, email, password, **kwargs):
        super().__init__(username=username, email=email, password=password, **kwargs)

    def __str__(self):
        return self.username

    @hybrid_property
    def password(self):
        return self._password

    @password.setter
    def password(self, value):
        self._password = bcrypt.generate_password_hash(value)

    @property
    def avatar(self):
        return Gravatar(self.email).get_image()

    def check_password(self, value):
        """Check password."""
        return bcrypt.check_password_hash(self.password, value)

    @property
    def addresses(self):
        return UserAddress.query.filter_by(user_id=self.id)

    @property
    def is_active_human(self):
        return "Y" if self.is_active else "N"

    @property
    def roles(self):
        at_ids = (
            UserRole.query.with_entities(UserRole.role_id)
            .filter_by(user_id=self.id)
            .all()
        )
        return Role.query.filter(Role.id.in_(id for id, in at_ids)).all()

    def delete(self):
        for addr in self.addresses:
            addr.delete()
        return super().delete()

    def can(self, permissions):
        if not self.roles:
            return False
        all_perms = reduce(or_, map(lambda x: x.permissions, self.roles))
        return all_perms & permissions == permissions

    def can_admin(self):
        return self.can(Permission.ADMINISTER)

    def can_edit(self):
        return self.can(Permission.EDITOR)