Пример #1
0
class SightingValidationRule(models.Model):

    # Rule info
    name = models.CharField(max_length=255)
    rank = positions.PositionField()

    # Rule conditions
    valid_photo = models.BooleanField("Photo is", choices=PHOTO_RESULT_TYPES)

    # Rule actions
    valid_sighting = models.BooleanField("Is sighting valid?",
                                         choices=SIGHTING_RESULT_TYPES)
    validation_message_template = models.ForeignKey(ValidationMessageTemplate)

    objects = SightingValidationRuleManager()

    def is_match(self, conditions):
        fails = [
            not ct.is_match(conditions) for ct in self.condition_tests.all()
        ]
        return not any(fails)

    class Meta:
        ordering = ['rank']

    def __unicode__(self):
        return self.name
Пример #2
0
class HelpPage(models.Model):
    topic = models.ForeignKey(Topic, verbose_name=_('topic'))
    path = models.CharField(
        _('path'),
        max_length=128,
        db_index=True,
        unique=True,
        help_text=('Use paths relative to your admin path '
                   '(<code>/admin/</code>). Examples: '
                   '<code>auth/user/</code>, <code>password_change/</code>, '
                   '<code>myapp/mymodel/</code>.'))
    title = models.CharField(_('title'), max_length=128)
    content = models.TextField(_('content'), blank=True)
    position = positions.PositionField(_('position'), collection=('topic', ))

    class Meta:
        ordering = ('topic', 'position', 'title')
        verbose_name = _('help page')
        verbose_name_plural = _('help pages')

    def __unicode__(self):
        return u'%s (%s)' % (self.title, self.path)

    def get_absolute_url(self):
        return ('help_page', None, {'id': str(self.id)})

    get_absolute_url = models.permalink(get_absolute_url)
Пример #3
0
class Item(WishlistBase):
    store = models.ForeignKey(
        'Store',
        on_delete=models.PROTECT,
    )
    platform = models.ForeignKey(
        'Platform',
        on_delete=models.PROTECT,
    )
    series = models.ForeignKey(
        'Series',
        on_delete=models.PROTECT,
        blank=True,
        null=True,
    )
    type = models.ForeignKey(
        'Type',
        on_delete=models.PROTECT,
    )
    name = models.CharField(max_length=64)
    position = positions.PositionField()
    objects = positions.PositionManager('position')
    url = models.URLField(blank=True)
    price = models.DecimalField(max_digits=6, decimal_places=2)
    image = models.ImageField(upload_to='wishlist/item/images/')

    def pos(self):
        return self.position + 1
Пример #4
0
class List(models.Model):
    name = models.CharField(max_length=256)
    user = models.ForeignKey(User)
    image = models.ImageField(null=True, blank=True, upload_to="list_images")
    slug = models.SlugField(null=True, blank=True)
    public = models.BooleanField(default=False, db_index=True)
    kind = models.IntegerField(choices=LIST_KIND_CHOICES,
                               default=2,
                               db_index=True)
    position = positions.PositionField(unique_for_fields=('user', 'kind'))
    count = models.PositiveIntegerField(default=0)

    created_time = models.DateTimeField(auto_now_add=True, db_index=True)
    modified_time = models.DateTimeField(auto_now=True, db_index=True)

    def __unicode__(self):
        return self.name

    def absolute_url(self):
        url = reverse('bookmark_list', args=(self.id, ))
        return url

    def top_ten(self):
        return self.bookmark_set.order_by('-created_time')[:10]

    class Meta:
        permissions = (
            ('can_view', 'Can view'),
            ('can_edit', 'Can edit'),
        )
Пример #5
0
class Item(models.Model):
    description = models.CharField(max_length=50)
    position = positions.PositionField()

    objects = positions.PositionManager()

    def __unicode__(self):
        return self.description
Пример #6
0
class Topic(models.Model):
    name = models.CharField(_('name'), max_length=64, unique=True, db_index=True)
    position = positions.PositionField(_('position'))

    class Meta:
        ordering = ('position', 'name')
        verbose_name = _('topic')
        verbose_name_plural = _('topics')

    def __unicode__(self):
        return u'%s' % self.name
Пример #7
0
class SponsorCategory(models.Model):
    name = models.CharField(max_length=255)
    order = positions.PositionField()

    objects = positions.PositionManager()

    class Meta:
        ordering = ['order']

    def __unicode__(self):
        return self.name
Пример #8
0
class Item(models.Model):
    description = models.CharField(max_length=50)

    # I'm calling the PositionField "index" to make sure any internal code that
    # relies on a PositionField being called "position" will break.
    # https://github.com/jpwatts/django-positions/pull/12
    index = positions.PositionField()

    objects = positions.PositionManager('index')

    def __unicode__(self):
        return self.description
Пример #9
0
class Faq(models.Model):

    title = models.CharField(max_length=255)
    content = models.TextField()
    order = positions.PositionField()

    objects = positions.PositionManager()

    class Meta:
        ordering = ['order']

    def __unicode__(self):
        return self.title
Пример #10
0
class Card(BaseModel):
    PREVIEWABLE_TYPES = (
        'link',
        'file',
    )
    TYPE_CHOICES = (
        ('link', 'Link'),
        ('note', 'Note'),
        ('file', 'File'),
        ('stack', 'Stack'),
    )

    name = models.CharField(max_length=255)
    type = models.CharField(max_length=5, choices=TYPE_CHOICES)
    slug = ReservedKeywordsAutoSlugField(
        editable=True,
        blank=True,
        populate_from='name',
        unique_with='board',
        reserved_keywords=CARD_RESERVED_KEYWORDS)

    board = models.ForeignKey('boards.Board')
    created_by = models.ForeignKey('users.User')
    modified_by = models.ForeignKey('users.User',
                                    related_name='%(class)s_modified_by')

    position = positions.PositionField(collection='board')

    stack = models.ForeignKey('cards.Card',
                              blank=True,
                              null=True,
                              related_name='+')
    cards = models.ManyToManyField('cards.Card',
                                   blank=True,
                                   null=True,
                                   related_name='+')

    featured = models.BooleanField(default=False)
    origin_url = models.URLField(blank=True, null=True)
    content = models.TextField(blank=True, null=True)

    is_shared = models.BooleanField(default=False)

    thumbnail_xs_path = models.TextField(blank=True, null=True)
    thumbnail_sm_path = models.TextField(blank=True, null=True)
    thumbnail_md_path = models.TextField(blank=True, null=True)
    thumbnail_lg_path = models.TextField(blank=True, null=True)

    file_size = models.IntegerField(blank=True, null=True)
    mime_type = models.CharField(max_length=255, blank=True, null=True)

    data = JSONField(blank=True,
                     null=True,
                     dump_kwargs={
                         'cls': JSONEncoder,
                         'separators': (',', ':')
                     })

    comments_count = models.PositiveIntegerField(default=0)
    comments = generic.GenericRelation('comments.Comment')

    objects = CardManager()

    class Meta:
        announce = True
        ordering = ['position']

    def __str__(self):
        return self.name

    def get_absolute_url(self):
        return reverse('card_detail',
                       kwargs={
                           'account_slug': self.board.account.slug,
                           'board_slug': self.board.slug,
                           'card_slug': self.slug
                       })

    @cached_property
    def html_url(self):
        return '{}{}'.format(settings.APPLICATION_URL, self.get_absolute_url())

    @cached_property
    def download_html_url(self):
        return '{}?download'.format(self.html_url)

    @cached_property
    def original_html_url(self):
        return '{}?original'.format(self.html_url)

    @cached_property
    def announce_room(self):
        return 'a{}'.format(self.board.account_id)

    @cached_property
    def serializer_class(self):
        from .serializers import CardSerializer
        return CardSerializer

    @cached_property
    def serializer(self):
        return self.serializer_class(self)

    @property
    def signed_thumbnail_xs_path(self):
        if self.thumbnail_xs_path:
            return sign_s3_url(self.thumbnail_xs_path)

    @property
    def signed_thumbnail_sm_path(self):
        if self.thumbnail_sm_path:
            return sign_s3_url(self.thumbnail_sm_path)

    @property
    def signed_thumbnail_md_path(self):
        if self.thumbnail_md_path:
            return sign_s3_url(self.thumbnail_md_path)

    @property
    def signed_thumbnail_lg_path(self):
        if self.thumbnail_lg_path:
            return sign_s3_url(self.thumbnail_lg_path)

    @property
    def download_url(self):
        expire_in = settings.AWS_SIGNATURE_EXPIRES_IN

        payload = {
            'type': 'CardDownload',
            'id': self.id,
            'exp': now() + datetime.timedelta(seconds=expire_in)
        }

        jwt_token = jwt.encode(payload, settings.SECRET_KEY)

        absolute_url = reverse('card_download',
                               kwargs={
                                   'account_slug': self.board.account.slug,
                                   'board_slug': self.board.slug,
                                   'card_slug': self.slug
                               })

        return '{}{}?token={}'.format(settings.APPLICATION_URL, absolute_url,
                                      jwt_token.decode('utf-8'))

    @property
    def file_download_url(self):
        if self.type == 'file':
            headers = {'response-content-disposition': 'attachment'}

            return sign_s3_url(self.content, response_headers=headers)

    @property
    def original_thumbnail_url(self):
        if not self.data:
            return None

        thumbnails = self.data.get('thumbnails')

        if not thumbnails:
            return None

        url = None

        for thumbnail in thumbnails:
            size = thumbnail.get('requested_size')
            resized = thumbnail.get('resized')

            if size == 'original' or not resized:
                url = thumbnail.get('url')
                break

        return sign_s3_url(url) if url else None

    @cached_property
    def pattern(self):
        if not self.data:
            return None

        pattern = self.data.get('pattern')

        if pattern:
            return {
                'shape': pattern.get('shape'),
                'color': pattern.get('color'),
            }

    @cached_property
    def metadata(self):
        if not self.data:
            return None

        return {'pattern': self.pattern}

    def save(self, *args, **kwargs):
        """
        Performs all steps involved in validating before
        model object is saved and sets modified_by
        from created_by when creating.
        """
        if not self.pk and not self.modified_by_id:
            self.modified_by_id = self.created_by_id

        self.clean()

        return super(Card, self).save(*args, **kwargs)

    def post_save(self, created, *args, **kwargs):
        # Notify card was created
        if created:
            self.notify_created()

        super(Card, self).post_save(created, *args, **kwargs)

    def clean(self):
        """
        Validates when card is a stack, that card specific fields arent' set.
        """
        string_fields = [
            'thumbnail_xs_path', 'thumbnail_sm_path', 'thumbnail_md_path',
            'thumbnail_lg_path', 'content', 'origin_url', 'mime_type'
        ]

        for field in string_fields:
            if field is None:
                setattr(self, field, '')

        if self.type != 'stack':
            if not self.content:
                raise ValidationError('The `content` field is required.')

            return None

        disallowed_fields = [
            'origin_url', 'content', 'thumbnail_xs_path', 'thumbnail_sm_path',
            'thumbnail_md_path', 'thumbnail_lg_path', 'file_size', 'mime_type'
        ]

        for field in disallowed_fields:
            if getattr(self, field):
                msg = 'The `{}` field should not be set on a card stack.'
                raise ValidationError(msg.format(field))

    def request_previews(self):
        if self.type not in self.PREVIEWABLE_TYPES or not self.content:
            return None

        destination = None

        if self.type == 'file':
            url = sign_s3_url(self.content)
        elif self.type == 'link':
            url = self.content
            destination = generate_file_key()

        sizes = ['original', '42>', '200>', '500>', '800>']

        metadata = {'cardId': self.id}

        return queue_previews(url,
                              sizes,
                              metadata,
                              uploader_destination=destination)

    def update_notification_data(self):
        """
        Updates thumbnail fields in notifications where this
        card is an action_object.
        """
        Notification = get_model('notifications', 'Notification')

        card_type = ContentType.objects.get_for_model(Card)
        notifications = Notification.objects.filter(
            action_object_content_type=card_type,
            action_object_object_id=self.id)

        update_fields = ('thumbnail_sm_path', 'thumbnail_md_path',
                         'thumbnail_lg_path')

        serializer = self.serializer_class(self, fields=update_fields)

        for notification in notifications:
            notification.data['action_object'].update(serializer.data)
            notification.save()

    def notify_created(self):
        user = self.created_by

        actor = user
        recipients = [user]

        if self.type == 'stack':
            label = 'card_stack_created'
        else:
            label = 'card_created'

        extra_context = {'action_object': self, 'target': self.board}

        notify.send(actor,
                    recipients=recipients,
                    label=label,
                    extra_context=extra_context)

    def notify_featured(self, user):
        actor = user
        recipients = [user]
        label = 'card_featured'

        extra_context = {'action_object': self, 'target': self.board}

        notify.send(actor,
                    recipients=recipients,
                    label=label,
                    extra_context=extra_context)

    def notify_comment_created(self, user, comment):
        recipients = []

        actor = user
        recipients = recipients
        label = 'card_comment_created'

        extra_context = {
            'action_object': comment,
            'description': comment.content,
            'target': self
        }

        notify.send(actor,
                    recipients=recipients,
                    label=label,
                    extra_context=extra_context)

    def update_comments_count(self, count=1):
        # Temporarily turn off announce
        self.set_announce(False)

        # Update comments count safely
        self.comments_count = F('comments_count') + count
        self.save()

        # Turn on announce
        self.set_announce(True)

        # Reload object and trigger post_save/announce
        card = Card.objects.get(pk=self.pk)
        card.post_save(instance=card, created=False)