Exemplo n.º 1
0
class Dispatcher(db.Document):
    path = db.StringField(primary_key=True)
    key = db.StringField(max_length=255)
    args = db.DictField()

    # dispatcher_map = DISPATCHER_KEYS

    meta = {'indexes': ['path']}

    @classmethod
    def create_or_change(cls, obj):
        # print getattr(obj, 'old_path'), getattr(obj, 'path')
        if hasattr(obj, 'path'):
            old_path = getattr(obj, 'old_path', None)
            dispatcher_key = obj.dispatcher_key
            path = obj.path

            if old_path and old_path != path:
                # Если пути не совпадают, взять объект по старому пути,
                # обновить путь. Старый путь сохранить в новый объект
                # для редиректа
                dispatcher = cls.objects(path=old_path).first()
                if dispatcher:
                    dispatcher.delete()

            dispatcher = cls(path=path, key=dispatcher_key)
            dispatcher.save()

    @classmethod
    def get_by_path(cls, path):
        dispatcher = cls.objects.get_or_404(path=path)
        return dispatcher.key
Exemplo n.º 2
0
class User(BaseModel):
    name = db.StringField()
    picture = db.StringField()

    @property
    def url(self):
        return USER_URL.format(self.id)
Exemplo n.º 3
0
class Order(db.Document):
    apishop_id = db.StringField(required=True)
    offers = db.ListField(db.EmbeddedDocumentField('OrderOffer'), default=[])
    ordered_at = db.DateTimeField()
    userinfo = db.DictField(default={})
    delivery_info = db.DictField(default={})
    comment = db.StringField()

    @property
    def get_delivery(self):
        return dict(price=self.delivery_info.get('delivery_price'),
                    total=self.delivery_info.get('order_sum')) \
            if self.delivery_info.get('delivery_price', None) is not None else None

    @property
    def get_total(self):
        return sum([offer.price * offer.quantity for offer in self.offers])

    def get_relevant_offers(self, max_items=4):
        offer_ids_not_to = [item.offer.id for item in self.offers]
        offer_ids = Offer.objects(available=True, id__nin=offer_ids_not_to).distinct('id')

        length = len(offer_ids)
        if length:
            try:
                ids = random.sample(offer_ids, max_items)
            except ValueError:
                ids = random.sample(offer_ids, length)

        return Offer.objects(id__in=ids)

    def get_timer(self):
        timer = self.ordered_at + timedelta(minutes=5) - timedelta(seconds=20)
        if timer < datetime.now():
            return False
        return timer.strftime('%Y/%m/%d %H:%M:%S')

    def add_offer(self, offer, quantity=1, variant=None):
        o = OrderOffer(offer=offer,
                       price=offer.get_price(),
                       oldprice=offer.get_oldprice or 0.0,
                       quantity=quantity,
                       variant=variant)
        self.update(push__offers=o)
        self.reload()

    def populate_offers(self, sended_offers):

        if not isinstance(sended_offers, (list, tuple)):
            sended_offers = [sended_offers]

        for sended_offer in sended_offers:
            offer = Offer.objects(articul=sended_offer.get('articul')).first()
            if offer:
                self.offers.append(OrderOffer(offer=offer,
                                              price=offer.get_price(),
                                              oldprice=offer.get_oldprice or 0.0,
                                              quantity=sended_offer.get('quantity', 1),
                                              variant=sended_offer.get('variant', None)))
Exemplo n.º 4
0
class Movie(BaseModel):
    name = db.StringField()
    mark = db.StringField()
    picture = db.StringField()

    meta = {'indexes': ['name']}

    @property
    def url(self):
        return MOVIE_URL.format(self.id)
Exemplo n.º 5
0
class Artist(BaseModel):
    name = db.StringField()
    picture = db.StringField()
    songs = db.ListField(db.ReferenceField('Song'))
    meta = {
        # 'indexes': ['name', '$name']  # 不支持text search?
        'indexes': ['name']
    }

    @property
    def url(self):
        return ARTIST_URL.format(self.id)
Exemplo n.º 6
0
class SmallBanner(Banner):
    bg_image = db.StringField(verbose_name=u'Фоновое изображение')
    link_to = db.StringField(verbose_name=u'Ссылка')
    header = db.StringField(max_length=100, verbose_name=u'Заголовок')
    bottom = db.StringField(max_length=200, verbose_name=u'Нижний текст')
    bottom_size = db.StringField(choices=(('sm', u'Маленький'), ('bg', u'Большой')),
                                 verbose_name=u'Размер нижнего текста')

    image_size = (400, 320)

    def generate_image_name(self):
        name = slugify(self.header)
        if self.bottom:
            name = slugify('-'.join([name, slugify(self.bottom)]))
        return name
Exemplo n.º 7
0
class PathMixin(SlugMixin):
    path = db.StringField(unique=True)

    def _check_path_exists(self):
        filters = dict(path=self.path)
        if self.id:
            filters['id__ne'] = self.id

        exist = self.__class__.objects(**filters).count()
        return exist

    def validate_path(self):
        self.old_path = self.path or None

        self.validate_slug()

        suffix = 1

        if hasattr(self, 'parent') and self.parent and self.parent != self:
            self.path = '/'.join([self.parent.path, self.slug])
        else:
            if hasattr(self, 'path_prefix'):
                self.path = '/'.join([getattr(self, 'path_prefix'), self.slug])
            else:
                self.path = self.slug

        while self._check_path_exists():
            self.path = '-'.join([self.path, str(suffix)])
            suffix += 1

    def save(self, *args, **kwargs):
        self.validate_path()
        super(PathMixin, self).save(*args, **kwargs)
Exemplo n.º 8
0
class ApishopConfig(TempDBMixin, db.Document):
    login = db.StringField(max_length=50, required=True)
    shop_id = db.IntField(required=True)
    yml_file = db.StringField(max_length=255)
    task = db.DictField(default={'id': None, 'name': None})
    updated_at = db.DateTimeField()

    _password = db.StringField(required=True)

    def __unicode__(self):
        return self.login

    @classmethod
    def get_config(cls):
        return cls.objects.first()

    @property
    def password(self):
        return decode_string(self._password)

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

    def set_task(self, task):
        self.update(set__task=dict(id=task.task_id, name=task.task_name))

    def set_updated_at(self):
        self.update(set__updated_at=datetime.datetime.now())

    @property
    def is_yml_exists(self):
        if self.yml_file:
            return check_file_exists(self.yml_file, relative=True)
        return False

    @property
    def task_is_ready(self):
        if self.task.get('id'):
            return celery.AsyncResult(self.task.get('id')).ready()
        return True

    def delete(self, *args, **kwargs):
        delete_file_by_path(self.yml_file, relative=True)
        ApishopCategory.objects.delete()
        ApishopOffer.objects.delete()
        super(ApishopConfig, self).delete(*args, **kwargs)
Exemplo n.º 9
0
class User(db.Document, UserMixin):
    email = db.StringField(max_length=255, unique=True)
    password = db.StringField(max_length=255, required=True)
    name = db.StringField(max_length=255)
    active = db.BooleanField(default=True)
    roles = db.ListField(db.ReferenceField(Role), default=[])
    registered_at = db.DateTimeField()

    def __unicode__(self):
        return 'User %s' % self.email

    @property
    def is_admin(self):
        return self.has_role('admin')

    def save(self, *args, **kwargs):
        self.registered_at = datetime.now()
        super(User, self).save(*args, **kwargs)
Exemplo n.º 10
0
class SlugMixin(object):
    slug = db.StringField(max_length=255, verbose_name=u'Ссылка')

    def validate_slug(self, name=None):
        if self.slug:
            self.slug = slugify(self.slug)
        else:
            self.slug = slugify(name if name else self.name)
        self.slug = slugify(self.slug)
Exemplo n.º 11
0
class Subscriber(IntIDMixin, db.Document):
    name = db.StringField(max_length=200, required=True)
    email = db.StringField(max_length=200, required=True)

    subscribed_at = db.DateTimeField(default=datetime.now())
    is_active = db.BooleanField(default=True)

    def __unicode__(self):
        return '<Subscriber {}: {}>'.format(self.id, self.email)

    def mark_subscribed(self):
        userinfo = session.get('userinfo', None)
        if not userinfo:
            session['userinfo'] = dict(fullname=self.name, email=self.email)
        else:
            if 'fullname' not in userinfo:
                userinfo['fullname'] = self.name
            if 'email' not in userinfo:
                userinfo['email'] = self.email

        session['is_subscribed'] = True
Exemplo n.º 12
0
class Vendor(DispatcherMixin, IntIDMixin, PathMixin, db.Document):
    name = db.StringField(max_length=255, verbose_name=u'Название')

    path_prefix = 'vendor'

    @classmethod
    def get_or_create_by_name(cls, name):
        vendor = cls.objects(name=name.strip()).first()
        if not vendor:
            vendor = cls(name=name.strip())
            vendor.save()
        return vendor
Exemplo n.º 13
0
class Review(db.Document):
    offer = db.ReferenceField('Offer')
    fullname = db.StringField(max_length=200)
    email = db.StringField(max_length=200)
    text = db.StringField()
    rating = db.IntField(default=0)
    is_moderated = db.BooleanField(default=False)
    is_viewed = db.BooleanField(default=False)
    created_at = db.DateTimeField(default=datetime.now)

    meta = {
        'ordering': ['-created_at']
    }

    def toggle_moderate(self):
        self.update(set__is_moderated=not self.is_moderated)
        self.reload()

    def set_viewed(self):
        if not self.is_viewed:
            self.update(set__is_viewed=True)
            self.reload()
Exemplo n.º 14
0
class Page(DispatcherMixin, PositionMixin, IntIDMixin,
           PathMixin, BreadcrumbsMixin, db.Document):

    name = db.StringField(max_length=255, verbose_name=u'Название', required=True)

    parent = db.ReferenceField('Page', default=None, verbose_name=u'Родитель')
    metas = db.EmbeddedDocumentField(Metas)

    content = db.StringField(verbose_name=u'Описание')

    extra = db.DictField(default={'type': 'None'})

    meta = {
        'ordering': ['+position'],
        'indexes': ['path',
                    'parent',
                    'position']
    }

    def __unicode__(self):
        return u'%s' % self.name

    def __repr__(self):
        return u'%s(%s)' % (self.__class__.__name__, self.id)

    @cached_property
    def get_title(self):
        if self.metas and self.metas.title:
            return self.metas.title

        return self.name

    def get_extra(self):
        return self.extra

    def save(self, *args, **kwargs):
        self.validate_position(kwargs.get('parent', self.parent))
        super(Page, self).save(*args, **kwargs)
Exemplo n.º 15
0
class DeliveryMethod(db.Document):
    id = db.IntField(primary_key=True)
    name = db.StringField(max_length=400)

    meta = {
        'ordering': ['+id'],
        'indexes': ['name']
    }

    def __unicode__(self):
        return self.name

    def __str__(self):
        return u'%s(%s)' % (self.__class__.__name__, self.id)
Exemplo n.º 16
0
class Song(BaseModel):
    name = db.StringField()
    comment_count = db.IntField()
    comments = db.ListField(db.ReferenceField('Comment'))
    artist = db.ReferenceField('Artist')
    meta = {'indexes': ['name']}

    @property
    def url(self):
        return SONG_URL.format(self.id)

    @property
    def artist_url(self):
        return self.artist.url
Exemplo n.º 17
0
class WideBanner(Banner):
    bg_image = db.StringField(verbose_name=u'Фоновое изображение')
    link_to = db.StringField(verbose_name=u'Ссылка')
    left_top = db.StringField(max_length=100, verbose_name=u'Слева сверху')
    left_bot = db.StringField(max_length=100, verbose_name=u'Слева снизу')
    right_top = db.StringField(max_length=100, verbose_name=u'Справа сверху')
    right_bot = db.StringField(max_length=100, verbose_name=u'Справа снизу')

    image_size = (320, 320)

    def generate_image_name(self):
        return slugify('-'.join([self.left_bot, self.right_bot]))
Exemplo n.º 18
0
class ApishopCategory(TempDBMixin, GetOrCreateMixin, db.Document):
    id = db.IntField(primary_key=True, unique=True)
    parent_id = db.IntField()
    name = db.StringField(max_length=255)
    category = db.ReferenceField(RealCategory, default=None)

    meta = {'indexes': ['parent_id', 'category']}

    def __unicode__(self):
        return self.name

    @classmethod
    def get_full_tree(cls):
        def build_tree(categories, parent_id=0):
            branch = []
            for index, category in enumerate(categories):
                if category.parent_id == parent_id:
                    form = ApishopCategoryLinkForm(request.form, obj=category)
                    branch.append(
                        dict(id=category.id,
                             name=category.name,
                             offers=category.get_offers_count,
                             form=form,
                             childs=build_tree(categories, category.id)))
            return branch

        categories = cls.objects.order_by('+parent_id')

        return build_tree(categories)

    @property
    def get_offers_count(self):
        return ApishopOffer.objects(category_id=self.id).count()

    @classmethod
    def copy_offers(cls):
        # Для каждой категории со связью отправить товар в RealOffer
        # для дальнейшей обработки и сохранения. После копирования очистить
        # базу временных товаров.
        categories_with_link = cls.objects(category__ne=None)
        for category in categories_with_link:
            for offer in ApishopOffer.objects(category_id=category.id):
                RealOffer.populate(offer, category.category)
Exemplo n.º 19
0
class Feature(db.Document):
    """A Point Feature

    valid Feature:
    - geometry: type: "Point", coordinates: <two-dim Array>
    - type: "Feature"
    - properties: a dict

    """

    type = db.StringField(default='Feature', choices=['Feature'])
    geometry = db.PointField(null=False)
    properties = db.DictField()

    meta = {
        'allow_inheritance': True,
        'abstract': True,
        'queryset_class': FeatureQuerySet
    }

    def to_feature(self):
        data = {
            'id':
            str(self.id),
            'type':
            self.type,
            'geometry':
            self.geometry,
            'properties':
            self.properties,
            'timestamp':
            str(self.id.generation_time),
            'uri':
            url_for('api.get_item',
                    collection=self.slug,
                    item_id=self.id,
                    _external=True)
        }
        return data

    def from_dict(self, data):
        self.geometry = data.get('geometry')
        self.properties = data.get('properties')
Exemplo n.º 20
0
class Admin(db.Document):
    _pwd = db.StringField(db_field='pwd')

    @property
    def pwd(self):
        return self._pwd

    @pwd.setter
    def pwd(self, value):
        try:
            self._pwd = bcrypt.generate_password_hash(value.encode('utf-8'))
        except (ValueError, AttributeError):
            raise ValueError('Cant set password. Probably empty value')

    def auth(self, plaintext):
        try:
            return bcrypt.check_password_hash(self._pwd.encode('utf-8'),
                                              plaintext.encode('utf-8'))
        except (ValueError, AttributeError, KeyError):
            return False
Exemplo n.º 21
0
class ApishopPriceChange(TempDBMixin, db.Document):
    oid = db.IntField()
    name = db.StringField()
    old_price = db.FloatField()
    new_price = db.FloatField()
    date = db.DateTimeField(default=datetime.datetime.now)

    meta = {'ordering': ['-date']}

    @classmethod
    def create_or_update(cls, **kwargs):
        oid = kwargs.pop('oid')

        obj = cls.objects(oid=oid)
        if len(obj) >= 1:
            for o in obj:
                o.delete()

        obj = cls(**kwargs)
        obj.save()
        return obj
Exemplo n.º 22
0
class ApishopOffer(TempDBMixin, GetOrCreateMixin, db.Document):
    id = db.IntField(primary_key=True)
    available = db.BooleanField()
    articul = db.StringField()
    price = db.DictField(default=dict(ru=None, by=None, kz=None))
    commissions = db.DictField(default=dict(ru=None, by=None, kz=None))
    category_id = db.IntField()
    name = db.StringField(max_length=255)
    model = db.StringField(max_length=255)
    vendor = db.StringField(max_length=100)
    pictures = db.ListField(db.StringField(max_length=255), default=[])
    description = db.StringField()
    variants = db.ListField(db.DictField())
    store_count = db.IntField()

    enabled_to_copy = db.BooleanField(default=True)

    meta = {'indexes': ['category_id']}

    def __unicode__(self):
        return '%s: %s' % (self.id, self.name)

    def get_picture(self):
        if len(self.pictures):
            return self.pictures[0]

    @property
    def prepare_to_copy(self):
        return dict(aid=self.id,
                    articul=self.articul,
                    available=self.available,
                    price=self.price,
                    commissions=self.commissions,
                    name=self.name,
                    model=self.model,
                    vendor=self.vendor,
                    pictures=[{
                        'url': picture
                    } for picture in self.pictures],
                    description=self.description,
                    stats=dict(store_count=self.store_count),
                    variants=[{
                        'store_count': variant.get('store_count'),
                        'aid': variant.get('id'),
                        'name': variant.get('name')
                    } for variant in self.variants])
Exemplo n.º 23
0
class BaseModel(db.Document):
    id = db.StringField(primary_key=True)
    create_at = db.DateTimeField(default=datetime.now())
    update_at = db.DateTimeField()

    meta = {"allow_inheritance": True, 'abstract': True, 'strict': False}

    @classmethod
    def get(cls, id):
        coll_name = cls._meta['collection']
        key = OBJ_KEY.format(coll_name=coll_name, id=id)
        rs = cache.get(key)
        if rs:
            return cls.from_json(rs)
        rs = cls.objects.get(id=id)
        cache.set(key, rs.to_json())
        return rs

    @classmethod
    def get_multi(cls, ids):
        return [cls.get(i) for i in ids if i]

    @classmethod
    def get_or_create(cls, **kwargs):
        try:
            return cls.objects.get(id=kwargs['id'])
        except DoesNotExist:
            kwargs.update({'update_at': datetime.now()})
            model = cls(**kwargs)
            model.save()
            return model

    @classmethod
    def get_sample_ids(cls, size):
        samples = list(cls.objects.aggregate({'$sample': {'size': size}}))
        return [s['_id'] for s in samples]
Exemplo n.º 24
0
class OrderOffer(db.EmbeddedDocument):
    offer = db.ReferenceField('Offer')
    price = db.FloatField(default=0.0)
    oldprice = db.FloatField(default=0.0)
    quantity = db.IntField(default=1)
    variant = db.StringField(default=None)
Exemplo n.º 25
0
class Comment(BaseModel):
    content = db.StringField()
    like_count = db.IntField()
    user = db.ReferenceField('User')
    song = db.ReferenceField('Song')
    meta = {'indexes': ['-like_count']}

    @property
    def user_url(self):
        return self.user.url

    @property
    def artist_url(self):
        return self.song.artist_url

    @classmethod
    def cache_by_key(cls, key, ids):
        """给内部用"""
        cache.delete(key)
        cache.rpush(key, *ids)
        cache.expire(key, TIMEOUT)

    @classmethod
    def get_random_by_session_id(cls, session_id, start=0, limit=20):
        """给API用"""
        key = RANDOM_KEY.format(session_id=session_id)
        if not start % SAMPLE_SIZE:
            ids = cls.get_sample_ids(SAMPLE_SIZE)
            cls.cache_by_key(key, ids)

        else:
            ids = cache.lrange(key, start, start + limit)
            if not ids:
                ids = cls.get_sample_ids(SAMPLE_SIZE)
                cls.cache_by_key(key, ids)

        comments = cls.get_multi(ids)
        return comments

    @classmethod
    def order_by_star(cls, start=0, limit=20):
        """给API用"""
        ids = cache.lrange(STAR_KEY, start, start + limit)
        if not ids:
            ids = [
                c.id for c in cls.objects.order_by('-like_count')[:TOTAL_SIZE]
            ]  # noqa
            cache.delete(STAR_KEY)
            cache.rpush(STAR_KEY, *ids)
            ids = ids[start:start + limit]
        return cls.get_multi(ids)

    def to_dict(self):
        song_obj = self.song
        user_obj = self.user
        artist_obj = song_obj.artist
        song = {'id': song_obj.id, 'url': song_obj.url, 'name': song_obj.name}

        artist = {
            'id': artist_obj.id,
            'avatar': artist_obj.picture,
            'name': artist_obj.name,
            'url': artist_obj.url
        }

        user = {
            'avatar': user_obj.picture,
            'name': user_obj.name,
            'url': user_obj.url
        }
        return {
            'song': song,
            'user': user,
            'artist': artist,
            'content': self.content
        }
Exemplo n.º 26
0
class RegionDelivery(db.EmbeddedDocument):
    method = db.StringField(max_length=400)
    id = db.IntField()
    price = db.FloatField()
Exemplo n.º 27
0
class Region(db.Document):
    id = db.IntField(primary_key=True)
    name = db.StringField(max_length=400)
    popularity = db.IntField(default=0)
    deliveries = db.ListField(db.EmbeddedDocumentField('RegionDelivery'),
                              default=[])

    updated_at = db.DateTimeField()

    meta = {
        'ordering': ['-popularity', '+id'],
        'indexes': ['name']
    }

    def __unicode__(self):
        return self.name

    def __str__(self):
        return u'%s(%s)' % (self.__class__.__name__, self.id)

    def int_popularity(self):
        popularity = (self.popularity or 0) + 1
        try:
            self.update(set__popularity=popularity)
        except db.OperationError:
            self.popularity = popularity
            self.save()

    def update_deliveries(self, methods):
        now = datetime.now()
        try:
            self.update(set__deliveries=methods, set__updated_at=now)
        except db.OperationError:
            self.deliveries = methods
            self.updated_at = now
            self.save()

    def get_delivery_prices(self, result, aid=None):
        d_methods = {str(d.id): {'id': d.id,
                                 'method': d.name} for d in DeliveryMethod.objects()}
        if not aid:
            aids = Offer.objects(available=True).distinct('aid')
            aid = random.choice(aids)

        methods = []

        if len(result):
            deliveries = result[0].deliveries
            for delivery in deliveries:
                d = d_methods.get(delivery.id, None)
                if d:
                    prices = []
                    for payment in delivery.payments:
                        price = payment.sum
                        if price is not None and price > 0 and price not in prices:
                            prices.append(price)

                    if len(prices):
                        price = min(prices)
                        d['price'] = price
                        methods.append(RegionDelivery(**d))
        return methods
Exemplo n.º 28
0
class Comment(BaseModel):
    content = db.StringField()
    like_count = db.IntField()
    user = db.ReferenceField('User')
    movie = db.ReferenceField('Movie', reverse_delete_rule=db.CASCADE)

    meta = {'indexes': ['-like_count']}

    @property
    def url(self):
        return COMMENT_URL.format(self.id)

    @property
    def user_url(self):
        return self.user.url

    @property
    def movie_url(self):
        return self.movie.url

    @classmethod
    def cache_by_key(cls, key, ids):
        cache.delete(key)
        cache.rpush(key, *ids)
        cache.expire(key, TIMEOUT)

    @classmethod
    def order_by_star(cls, start=0, limit=20):
        ids = cache.lrange(START_KEY, start, start + limit)
        if not ids:
            ids = [
                c.id for c in cls.objects.order_by('-like_count')[:TOTAL_SIZE]
            ]
            cache.delete(START_KEY)
            cache.rpush(START_KEY, *ids)
            ids = ids[start:start + limit]
        return cls.get_multi(ids)

    def to_dict(self):
        movie_obj = self.movie
        user_obj = self.user

        movie = {
            'id': movie_obj.id,
            'name': movie_obj.name,
            'mark': movie_obj.mark,
            'url': movie_obj.url,
            'picture': movie_obj.picture
        }

        user = {
            'id': user_obj.id,
            'avatar': user_obj.picture,
            'name': user_obj.name,
        }

        return {
            'movie': movie,
            'user': user,
            'content': self.content,
            'like_count': self.like_count
        }
Exemplo n.º 29
0
class Role(db.Document, RoleMixin):
    name = db.StringField(max_length=255, unique=True)
    description = db.StringField(max_length=255)

    def __unicode__(self):
        return self.name
Exemplo n.º 30
0
class Banner(db.Document):
    banner_type = db.StringField(choices=type_choices, default=u'small',
                                 max_length=100, verbose_name=u'Тип баннера')
    bg_color = db.StringField(default='#333333', max_length=7, verbose_name=u'Цвет фона')

    is_enabled = db.BooleanField(default=True)

    meta = {
        'allow_inheritance': True
    }

    @classmethod
    def get_class_by_group(cls, group):
        return eval('{}Banner'.format(group.capitalize()))

    @classmethod
    @cache.memoize(60)
    def get_banners_grouped(cls, only_enabled=True):
        filters = {}
        if only_enabled:
            filters['is_enabled'] = True

        banners = cls.objects(**filters)

        grouped_banners = {}
        for banner in banners:
            if banner.banner_type in grouped_banners:
                grouped_banners[banner.banner_type].append(banner)
            else:
                grouped_banners[banner.banner_type] = [banner]
        return grouped_banners

    @classmethod
    def get_banners(cls, group=None, only_enabled=True):
        banners = cls.get_banners_grouped(only_enabled)

        grouped_banners = {}
        for g, bs in banners.items():
            path = request.path
            new_bs = []
            for b in bs:
                if path != b.link_to:
                    new_bs.append(b)
            max = max_banners_items.get('MAX_{}_BANNERS'.format(g.upper()))
            random.shuffle(new_bs)
            if len(new_bs) > max:
                new_bs = new_bs[:max]
            grouped_banners[g] = new_bs

        if group:
            return grouped_banners.get(group, [])

        return grouped_banners

    @property
    def get_link_to(self):
        if not self.link_to:
            return url_for('site.index')
        return '/{}/'.format(self.link_to.strip('/'))

    def generate_image_name(self):
        return str(self.id)

    def upload_image(self, file):
        size = self.image_size or (300, 300)
        original = upload_file(file, self.generate_image_name(), 'banners')
        image = create_offer_image(original, format='png', width=size[0], height=size[1], suffix='b',
                                   fill=0, quality=100)

        if os.path.exists(os.path.join(current_app.config.get('MEDIA_DIR'), original)):
            os.remove(os.path.join(current_app.config.get('MEDIA_DIR'), original))

        return image


    def save(self, *args, **kwargs):
        cache.delete_memoized(Banner.get_banners_grouped)
        super(Banner, self).save(*args, **kwargs)