def test_update_position(self): api_key = self.__login("user", "pass") headers = self.__build_headers("user", api_key) article = Article.objects.create( title="Article", slug="article", category=self.category, publish_from=timezone.now() ) recipe = Article.objects.create( title="Spinach", slug="spinach", category=self.category, publish_from=timezone.now() ) position = Position.objects.create(name="Position", category=self.category, target=article) payload = simplejson.dumps( { "name": "Updated name :)", "category": "/admin-api/category/%d/" % self.category_nested.id, "target": "/admin-api/article/%d/" % recipe.id, } ) response = self.client.put( "/admin-api/position/%d/" % position.id, payload, content_type="application/json", **headers ) tools.assert_equals(response.status_code, 202) position = Position.objects.get(pk=position.pk) tools.assert_equals(position.name, "Updated name :)") tools.assert_equals(position.category, self.category_nested) tools.assert_equals(position.target, recipe) position.delete() article.delete() recipe.delete() self.__logout(headers)
def test_generate_picks_up_on_publish(self): self.publishable.publish_from = timezone.now() + timedelta(days=1) self.publishable.save() self._signal_clear() generate_publish_signals(timezone.now() + timedelta(days=1, seconds=2)) tools.assert_equals(1, len(self.publish_received)) tools.assert_equals(0, len(self.unpublish_received)) tools.assert_equals(self.publishable, self.publish_received[0]['publishable'].target)
def test_publish_to_unpublishes_at_time(self): publish_to = timezone.now() - timedelta(hours=1) self.publishable.publish_to = publish_to self.publishable.published = True self.publishable.save() tools.assert_equals(1, len(Publishable.objects.filter(published=True, publish_to=publish_to))) unpublish_publish_to_expirations(timezone.now()) tools.assert_equals(0, len(Publishable.objects.filter(published=True, publish_to=publish_to)))
def _get_score_limits(self): max_score = repr(to_timestamp(now())) min_score = 0 if self.date_range: max_score = repr(to_timestamp(min(self.date_range[1], now()))) min_score = repr(to_timestamp(self.date_range[0])) return min_score, max_score
def test_active_from_till_no_match(self): p = Position.objects.create( category=self.category, name='position-name', text='some text', active_from=now() - timedelta(days=3), active_till=now() - timedelta(days=1), ) tools.assert_raises(Position.DoesNotExist, Position.objects.get_active_position, self.category, 'position-name')
def setUp(self): self.user = self.__create_test_user("user", "pass", True) create_basic_categories(self) self.article = Article.objects.create(title="Jop", slug="jop", category=self.category, publish_from=timezone.now()) self.recipe = Article.objects.create(title="Spinach", slug="spinach", category=self.category_nested, publish_from=timezone.now()) self.encyclopedia = Article.objects.create(title="Enc", slug="enc", category=self.category, publish_from=timezone.now())
def test_active_from_till_match(self): p = Position.objects.create( category=self.category, name='position-name', text='some text', active_from=now() - timedelta(days=1), active_till=now() + timedelta(days=1), ) tools.assert_equals( p, Position.objects.get_active_position(self.category_nested, 'position-name'))
def setUp(self): self.user = self.__create_test_user("user", "pass", True) self.client = Client() init_ella_workflow(get_all_resource_classes()) create_basic_categories(self) Article.objects.create(title="Jop", slug="jop", category=self.category, publish_from=timezone.now()) Article.objects.create(title="Spinach", category=self.category_nested, publish_from=timezone.now(), slug="spinach") Article.objects.create(title="Jop3", category=self.category, publish_from=timezone.now(), slug="jop3")
def current(self, now=None): now = timezone.now().replace(second=0, microsecond=0) return self.filter(models.Q(publish_to__isnull=True) | models.Q(publish_to__gt=now), published=True, publish_from__lte=now)
def setUp(self): super(QuizTestCase, self).setUp() create_basic_categories(self) self.quiz = Quiz.objects.create( title=u'First Quiz', slug=u'first-quiz', description=u'First quiz', category=self.category_nested, publish_from=now(), published=True, intro_title='Answer me!', intro_text='Some even longer test. \n' * 5, choices=3 ) self.results = [ Result.objects.create( quiz=self.quiz, choice=ch, text='You chose %d' % ch ) for ch in range(3) ] self.questions = [ Question.objects.create( quiz=self.quiz, order=x, text='WTF %d?!' % x, choices_data=Question.SEPARATOR.join('%d FTW!' % ch for ch in range(3)) ) for x in range(3) ]
def test_listing_gets_removed_when_publishable_marked_unpublished_even_if_not_published_yet( self): future = now() + timedelta(days=1) p = self.publishables[0] p.publish_from = future p.save() list_all_publishables_in_category_by_hour(self) p.published = False p.save() ct_id = p.content_type_id tools.assert_equals( set([ 'listing:2', 'listing:3', 'listing:c:1', 'listing:c:2', 'listing:c:3', 'listing:d:1', 'listing:d:2', 'listing:d:3', 'listing:ct:%d' % ct_id, ]), set(redis.client.keys())) tools.assert_equals(['%d:2' % ct_id, '%d:3' % ct_id], redis.client.zrange('listing:ct:%d' % ct_id, 0, 100)) tools.assert_equals(['%d:2' % ct_id, '%d:3' % ct_id], redis.client.zrange('listing:d:1', 0, 100)) tools.assert_equals(['%d:2' % ct_id], redis.client.zrange('listing:c:1', 0, 100))
def test_last_updated_isnt_moved_if_changed(self): now = timezone.now() self.publishable.last_updated = now + timedelta(days=1) self.publishable.publish_from = now self.publishable.save(force_update=True) tools.assert_equals(now + timedelta(days=1), self.publishable.last_updated)
def is_active(self, obj): if obj.disabled: return False now = timezone.now() active_from = not obj.active_from or obj.active_from <= now active_till = not obj.active_till or obj.active_till > now return active_from and active_till
def current(self, now=None): now = timezone.now().replace(second=0, microsecond=0) return self.filter( models.Q(publish_to__isnull=True) | models.Q(publish_to__gt=now), published=True, publish_from__lte=now )
def test_rotate_image_photo_with_missing_photos_directory(self): api_key = self.__login("user", "pass") headers = self.__build_headers("user", api_key) rmtree(os.path.join( settings.MEDIA_ROOT, force_unicode(now().strftime(smart_str(photos_settings.UPLOAD_TO))), )) file = open(self.photo_filename) payload = { "attached_object": file, "resource_data": json.dumps({ "objects": [ { "title": "Rotated photo", "image": "attached_object_id:" + os.path.basename(self.photo_filename), "authors": ["/admin-api/author/%d/" % self.author.id], "created": "2012-10-27T12:48:29", "rotate": 90, } ] }), } response = self.patch("/admin-api/photo/", payload, **headers) tools.assert_equals(response.status_code, 202, response.content) file.close() self.__logout(headers)
def regenerate_listing_handlers(today=None): if today is None: today = timezone.now().date() Listing.objects.get_listing_handler('default') for lh in Listing.objects._listing_handlers.values(): lh.regenerate(today)
def setUp(self): super(QuizTestCase, self).setUp() create_basic_categories(self) self.quiz = Quiz.objects.create( title=u'First Quiz', slug=u'first-quiz', description=u'First quiz', category=self.category_nested, publish_from=now(), published=True, intro_title='Answer me!', intro_text='Some even longer test. \n' * 5, choices=3) self.results = [ Result.objects.create(quiz=self.quiz, choice=ch, text='You chose %d' % ch) for ch in range(3) ] self.questions = [ Question.objects.create(quiz=self.quiz, order=x, text='WTF %d?!' % x, choices_data=Question.SEPARATOR.join( '%d FTW!' % ch for ch in range(3))) for x in range(3) ]
def test_more_positions_one_active(self): n = now() p1 = Position.objects.create(category=self.category, name='position-name', text='some text', active_from=n-timedelta(days=1), ) p2 = Position.objects.create(category=self.category, name='position-name', text='some text', active_till=n-timedelta(days=1)) tools.assert_equals(p1, Position.objects.get_active_position(self.category_nested, 'position-name'))
def get_active_position(self, category, name, nofallback=False): """ Get active position for given position name. params: category - Category model to look for name - name of the position nofallback - if True than do not fall back to parent category if active position is not found for category """ now = timezone.now() lookup = (Q(active_from__isnull=True) | Q(active_from__lte=now)) & \ (Q(active_till__isnull=True) | Q(active_till__gt=now)) while True: try: return self.get(lookup, category=category, name=name, disabled=False) except Position.DoesNotExist: # if nofallback was specified, do not look into parent categories if nofallback: return False # traverse the category tree to the top otherwise category = category.tree_parent # we reached the top and still haven't found the position - return if category is None: return False
def test_listing_gets_removed_when_publishable_marked_unpublished_even_if_not_published_yet(self): future = now() + timedelta(days=1) p = self.publishables[0] p.publish_from = future p.save() list_all_publishables_in_category_by_hour(self) p.published = False p.save() ct_id = p.content_type_id tools.assert_equals(set([ 'listing:2', 'listing:3', 'listing:c:1', 'listing:c:2', 'listing:c:3', 'listing:d:1', 'listing:d:2', 'listing:d:3', 'listing:ct:%d' % ct_id, ]), set(redis.client.keys()) ) tools.assert_equals(['%d:2' % ct_id, '%d:3' % ct_id], redis.client.zrange('listing:ct:%d' % ct_id, 0, 100)) tools.assert_equals(['%d:2' % ct_id, '%d:3' % ct_id], redis.client.zrange('listing:d:1', 0, 100)) tools.assert_equals(['%d:2' % ct_id], redis.client.zrange('listing:c:1', 0, 100))
def regenerate_publish_signals(now=None): if now is None: now = timezone.now() qset = Publishable.objects.filter(publish_from__lt=now, published=True).exclude(publish_to__lt=now) for p in qset: content_published.send(sender=p.content_type.model_class(), publishable=p)
def post_comment(request, context, comment_id=None): clist = CommentList.for_object(context['object']) if clist.locked(): return TemplateResponse(request, get_template('comments_locked.html', context['object'], request.is_ajax()), context, status=403) comment = None user = request.user if comment_id: try: comment = clist.get_comment(comment_id) except FlatComment.DoesNotExist: raise Http404() # make sure we don't change user when mod is editting a comment user = comment.user # you can only comment your own comments or you have to be a moderator if comment.user != request.user and not comments_settings.IS_MODERATOR_FUNC( request.user): return HttpResponseForbidden( "You cannot edit other people's comments.") data, files = None, None if request.method == 'POST': data, files = request.POST, request.FILES form = FlatCommentMultiForm(context['object'], user, data=data, files=files, instance=comment) if form.is_valid(): comment, success, reason = form.post() if not success: return HttpResponseForbidden(reason) comment_updated.send(sender=comment.__class__, comment=comment, updating_user=request.user, date_updated=now()) if request.is_ajax(): return TemplateResponse( request, get_template('comment_detail_async.html', context['object']), context) return HttpResponseRedirect( comment.get_absolute_url(show_reversed(request))) context.update({'comment': comment, 'form': form}) return TemplateResponse( request, get_template('comment_form.html', context['object'], request.is_ajax()), context)
def setUp(self): self.user = self.__create_test_user("user", "pass", is_admin=True) self.client = Client() create_basic_categories(self) self.publishable = Article.objects.create(title="Spinach", category=self.category_nested, publish_from=timezone.now(), slug="spinach-ou-jeee")
def is_closed(self): """ Returns True if the object is in the closed life-cycle stage. Otherwise returns False """ if self.active_till and self.active_till < now(): return True return False
def test_active_till_past(self): p = Position.objects.create(category=self.category, name='position-name', text='some text', active_till=now() - timedelta(days=1)) tools.assert_false( Position.objects.get_active_position(self.category, 'position-name'))
def unpublish_publish_to_expirations(now=None): if now is None: now = timezone.now() pubs = Publishable.objects.filter(publish_to__lt=now, published=True) for p in pubs: p.published = False p.save()
def test_active_from_future(self): p = Position.objects.create(category=self.category, name='position-name', text='some text', active_from=now() + timedelta(days=1)) tools.assert_raises(Position.DoesNotExist, Position.objects.get_active_position, self.category, 'position-name')
def test_inactive_istings_wont_show(self): l = self.listings[0] l.publish_to = now() - timedelta(days=1) l.save() l = Listing.objects.get_listing(category=self.category, children=ListingHandler.ALL) tools.assert_equals(self.listings[1:], l)
def get_listing_queryset(self, category=None, children=ListingHandler.NONE, content_types=[], date_range=(), exclude=None, **kwargs): # give the database some chance to cache this query now = timezone.now().replace(second=0, microsecond=0) if date_range: qset = self.filter(publish_from__range=date_range, publishable__published=True, **kwargs) else: qset = self.filter(publish_from__lte=now, publishable__published=True, **kwargs) if category: if children == ListingHandler.NONE: # only this one category qset = qset.filter(category=category) elif children == ListingHandler.IMMEDIATE: # this category and its children qset = qset.filter( models.Q(category__tree_parent=category) | models.Q(category=category)) for c in category.get_children(): if not c.app_data.ella.propagate_listings: qset = qset.exclude(category=c) elif children == ListingHandler.ALL: # this category and all its descendants qset = qset.filter( category__tree_path__startswith=category.tree_path, category__site=category.site_id) for c in category.get_children(True): if not c.app_data.ella.propagate_listings: qset = qset.exclude( category__tree_path__startswith=c.tree_path) else: raise AttributeError( 'Invalid children value (%s) - should be one of (%s, %s, %s)' % (children, self.NONE, self.IMMEDIATE, self.ALL)) # filtering based on Model classes if content_types: qset = qset.filter(publishable__content_type__in=content_types) # we were asked to omit certain Publishable if exclude: qset = qset.exclude(publishable=exclude) return qset.exclude(publish_to__lt=now).order_by('-publish_from')
def publish_from_nice(self, obj): span_str = '<span class="%s">%s</span>' date_str = date(obj.publish_from, settings.DATETIME_FORMAT) if obj.publish_from.year >= 3000: return mark_safe(span_str % ('unpublished', ugettext('No placement'))) elif obj.publish_from > now(): return span_str % ('unpublished', date_str) return span_str % ('published', date_str)
def approve(self, user=None): self.moderation_user = user self.moderation_date = now() self.status = self.STATUS_APPROVED self.save() self.wiki.submission = self self.wiki.content = self.content self.wiki.save(force_update=True)
def regenerate_publish_signals(now=None): if now is None: now = timezone.now() qset = Publishable.objects.filter( publish_from__lt=now, published=True).exclude(publish_to__lt=now) for p in qset: content_published.send(sender=p.content_type.model_class(), publishable=p)
def upload_to(instance, filename): name, ext = os.path.splitext(filename) name = instance.slug and instance.slug or slugify(name) file_name = ''.join([name, ext.lower()]) return os.path.join( force_text(now().strftime(smart_str(attachments_settings.UPLOAD_TO))), file_name )
def _upload_to(self, filename): name, ext = os.path.splitext(filename) ext = ext.lower() ext = photos_settings.TYPE_EXTENSION.get(ext, ext) return os.path.join( get_media_drafts_root(), force_unicode(now().strftime(smart_str(photos_settings.UPLOAD_TO))), slugify(name) + ext )
def test_get_listing_with_all_children_no_duplicates(self): listing = Listing.objects.create( publishable=self.publishables[0], category=self.category_nested_second, publish_from=now() - timedelta(days=2), ) l = Listing.objects.get_listing(category=self.category, children=ListingHandler.ALL) tools.assert_equals(len(self.listings), len(l)) tools.assert_equals(listing, l[0])
def upload_to(instance, filename): name, ext = os.path.splitext(filename) if instance.slug: name = instance.slug ext = photos_settings.TYPE_EXTENSION.get(instance._get_image().format, ext.lower()) return os.path.join( force_unicode(now().strftime(smart_str(photos_settings.UPLOAD_TO))), name + ext )
def upload_to(instance, filename): name, ext = os.path.splitext(filename) if instance.slug: name = instance.slug ext = photos_settings.TYPE_EXTENSION.get(instance._get_image().format, ext.lower()) return os.path.join( force_unicode(now().strftime(smart_str(photos_settings.UPLOAD_TO))), name + ext)
def setUp(self): create_basic_categories(self) self.publishable = Article.objects.create(title=u"Title like a boss", category=self.category, slug="title-article", publish_from=now()) User.objects.all().delete() self.user = self.__create_user("user", "pass", is_admin=True) self.locker_user = self.__create_user("lock", "pass", is_admin=True) self.lock = PublishableLock.objects.lock(self.publishable, self.locker_user)
def test_get_listing_with_immediate_children_no_duplicates(self): expected = [listing for listing in self.listings if listing.category in (self.category, self.category_nested)] listing = Listing.objects.create( publishable=expected[0].publishable, category=expected[0].category, publish_from=now() - timedelta(days=2), ) expected[0] = listing l = Listing.objects.get_listing(category=self.category, children=ListingHandler.IMMEDIATE) tools.assert_equals(expected, l)
def post_comment(request, context, comment_id=None): clist = CommentList.for_object(context['object']) if clist.locked(): return TemplateResponse(request, get_template('comments_locked.html', context['object'], request.is_ajax()), context, status=403) comment = None user = request.user if comment_id: try: comment = clist.get_comment(comment_id) except FlatComment.DoesNotExist: raise Http404() # make sure we don't change user when mod is editting a comment user = comment.user # you can only comment your own comments or you have to be a moderator if comment.user != request.user and not comments_settings.IS_MODERATOR_FUNC(request.user): return HttpResponseForbidden("You cannot edit other people's comments.") # Don't allow users to edit a comment after the allowed edit time has expired if comment.user == request.user and not comments_settings.IS_MODERATOR_FUNC(request.user) and comment.is_edit_timer_expired(): if request.is_ajax(): context.update({'comment': comment}) return TemplateResponse(request, get_template('comment_detail_async.html', context['object']), context) return HttpResponseForbidden("The allowed time to edit the comment has expired.") data, files = None, None if request.method == 'POST': data, files = request.POST, request.FILES form = FlatCommentMultiForm(context['object'], user, data=data, files=files, instance=comment) if form.is_valid(): comment, success, reason = form.post(request) if not success: return HttpResponseForbidden(reason) comment_updated.send( sender=comment.__class__, comment=comment, updating_user=request.user, date_updated=now() ) if request.is_ajax(): context.update({'comment': comment}) return TemplateResponse(request, get_template('comment_detail_async.html', context['object']), context) return HttpResponseRedirect(comment.get_absolute_url(show_reversed(request))) context.update({ 'comment': comment, 'form': form }) return TemplateResponse(request, get_template('comment_form.html', context['object'], request.is_ajax()), context)
def validate_api_key_view(self, request): try: self.ensure_authenticated(request) except: return self.__build_response(False) try: api_key = ApiKey.objects.get(user=request.user) except ApiKey.DoesNotExist: return self.__build_response(False) else: expiration_time = api_key.created + datetime.timedelta(days=conf.API_KEY_EXPIRATION_IN_DAYS) return self.__build_response(timezone.now() < expiration_time)
def _archive_entry_year(self, category): " Return ARCHIVE_ENTRY_YEAR from settings (if exists) or year of the newest object in category " year = getattr(settings, 'ARCHIVE_ENTRY_YEAR', None) if not year: n = now() try: year = Listing.objects.filter( category__site__id=settings.SITE_ID, category__tree_path__startswith=category.tree_path, publish_from__lte=n ).values('publish_from')[0]['publish_from'].year except: year = n.year return year
def _archive_entry_year(self, category): " Return ARCHIVE_ENTRY_YEAR from settings (if exists) or year of the newest object in category " year = getattr(settings, 'ARCHIVE_ENTRY_YEAR', None) if not year: n = now() try: year = Listing.objects.filter( category__site__id=settings.SITE_ID, category__tree_path__startswith=category.tree_path, publish_from__lte=n).values( 'publish_from')[0]['publish_from'].year except: year = n.year return year
def test_get_listing_with_immediate_children_no_duplicates(self): expected = [ listing for listing in self.listings if listing.category in (self.category, self.category_nested) ] listing = Listing.objects.create( publishable=expected[0].publishable, category=expected[0].category, publish_from=now() - timedelta(days=2), ) expected[0] = listing l = Listing.objects.get_listing(category=self.category, children=ListingHandler.IMMEDIATE) tools.assert_equals(expected, l)
def add_publishable(cls, category, publishable, score=None, publish_from=None, pipe=None, commit=True): if score is None: score = repr(to_timestamp(publish_from or now())) return super(TimeBasedListingHandler, cls).add_publishable(category, publishable, score, pipe=pipe, commit=commit)
def test_more_positions_one_active(self): n = now() p1 = Position.objects.create( category=self.category, name='position-name', text='some text', active_from=n - timedelta(days=1), ) p2 = Position.objects.create(category=self.category, name='position-name', text='some text', active_till=n - timedelta(days=1)) tools.assert_equals( p1, Position.objects.get_active_position(self.category_nested, 'position-name'))
def generate_publish_signals(now=None): if now is None: now = timezone.now() # content that went live and isn't announced yet qset = Publishable.objects.filter( announced=False, publish_from__lt=now, published=True).exclude(publish_to__lt=now) for p in qset: content_published.send(sender=p.content_type.model_class(), publishable=p) qset.update(announced=True) # content that went down but was announced as live qset = Publishable.objects.filter(announced=True, publish_to__lt=now, published=True) for p in qset: content_unpublished.send(sender=p.content_type.model_class(), publishable=p) qset.update(announced=False)
def test_last_updated_moved_if_default(self): now = timezone.now() self.publishable.publish_from = now self.publishable.save(force_update=True) tools.assert_equals(now, self.publishable.last_updated)
def clean_listings(self): """ Method that cleans the Listing model by deleting all listings that are no longer valid. Should be run periodicaly to purge the DB from unneeded data. """ self.filter(publish_to__lt=timezone.now()).delete()
def is_published(self): "Return True if the Publishable is currently active." cur_time = now() return self.published and cur_time > self.publish_from and \ (self.publish_to is None or cur_time < self.publish_to)
def create_and_place_two_publishables_and_listings(case): """ Create two articles and listings """ def place_publishable(model, title, slug, description, category, publish_from, publish_to=None, published=True): pu = model.objects.create(title=title, slug=slug, description=description, category=category, publish_from=publish_from, publish_to=publish_to, published=published) li = Listing.objects.create(publishable=pu, category=c, publish_from=pu.publish_from, publish_to=publish_to) case.publishables.append(pu) case.listings.append(li) c = case.category now = timezone.now() case.publishables = [] case.listings = [] case.hitcounts_all = [] case.hitcounts_age_limited = [] case.hitcounts_galleries = [] publish_from = now - timedelta(days=90) publish_to = now - timedelta(days=30) place_publishable( model=Article, title=u'Inactive', slug=u'article-inactive', description=u'Some\nlonger\ntext', category=c, publish_from=publish_from.date(), publish_to=publish_to.date(), ) publish_from = timezone.now() - timedelta(days=8) place_publishable(model=Article, title=u'Newer', slug=u'article-newer', description=u'Some\nlonger\ntext', category=c, publish_from=now.date()) publish_from = now + timedelta(days=1) place_publishable(model=Article, title=u'Future', slug=u'article-future', description=u'Some\nlonger\ntext', category=c, publish_from=publish_from.date())
def save(self, **kwargs): if self.submit_date is None: self.submit_date = timezone.now() super(FlatComment, self).save(**kwargs)