def test_menu_nodes(self): """ Tests if all categories are present in the menu """ posts = self.get_posts() pages = self.get_pages() self.reload_urlconf() for lang in ('en', 'it'): with smart_override(lang): request = self.get_page_request(pages[1], self.user, pages[1].get_absolute_url(lang)) nodes = menu_pool.get_nodes(request) nodes_url = set([node.url for node in nodes]) cats_url = set([cat.get_absolute_url() for cat in self.cats if cat.has_translation(lang)]) self.assertTrue(cats_url.issubset(nodes_url)) cache.clear() posts[0].categories.clear() for lang in ('en', 'it'): with smart_override(lang): request = self.get_page_request(pages[1], self.user, pages[1].get_absolute_url(lang)) nodes = menu_pool.get_nodes(request) nodes_url = set([node.url for node in nodes]) self.assertFalse(posts[0].get_absolute_url(lang) in nodes_url) self.assertTrue(posts[1].get_absolute_url(lang) in nodes_url)
def test_menu_nodes(self): """ Tests if all categories are present in the menu """ pages = self.get_pages() posts = self.get_posts() self.reload_urlconf() for lang in ('en', 'it'): with smart_override(lang): request = self.get_page_request(pages[1], self.user, pages[1].get_absolute_url(lang)) nodes = menu_pool.get_nodes(request) nodes_url = set([node.url for node in nodes]) cats_url = set([cat.get_absolute_url() for cat in self.cats if cat.has_translation(lang)]) self.assertTrue(cats_url.issubset(nodes_url)) cache.clear() posts[0].categories.clear() for lang in ('en', 'it'): with smart_override(lang): request = self.get_page_request(pages[1], self.user, pages[1].get_absolute_url(lang)) nodes = menu_pool.get_nodes(request) nodes_url = set([node.url for node in nodes]) self.assertFalse(posts[0].get_absolute_url(lang) in nodes_url) self.assertTrue(posts[1].get_absolute_url(lang) in nodes_url)
def test_parler_model_attributes(self): posts = [] with smart_override('en'): posts.append(MultiLanguagePost.objects.create( title='first post', slug='first-post', )) posts.append(MultiLanguagePost.objects.create( title='second post', slug='second-post', )) posts[0].create_translation( 'it', title='primo articolo', slug='primo-articolo' ) posts[1].create_translation( 'it', title='secondo articolo', slug='secondo-articolo' ) posts[0].create_translation( 'fr', title='premier article', slug='premier-article' ) for post in posts: for language in post.get_available_languages(): with smart_override(language): post.set_current_language(language) if language != 'fr': knock_create = post.as_knock(True) self.assertEqual(knock_create['title'], 'new {0}'.format(post._meta.verbose_name)) self.assertEqual(knock_create['message'], post.title) self.assertEqual(knock_create['language'], language) post.send_knock(True) knock_create = post.as_knock(False) self.assertEqual(knock_create['title'], 'new {0}'.format(post._meta.verbose_name)) self.assertEqual(knock_create['message'], post.title) self.assertEqual(knock_create['language'], language) post.send_knock(False) else: self.assertFalse(post.should_knock()) self.assertFalse(post.as_knock(True)) self.assertFalse(post.as_knock(False)) post.send_knock(False)
def test_post_list_view_fallback(self): pages = self.get_pages() self.get_posts() PARLER_FALLBACK = { # noqa: N806 1: ( {"code": "en"}, {"code": "it"}, {"code": "fr", "hide_untranslated": True}, ), "default": {"fallback": "en", "hide_untranslated": False}, } with smart_override("fr"): view_obj = PostListView() request = self.get_page_request(pages[1], self.user, lang="fr", edit=True) view_obj.request = request view_obj.namespace, view_obj.config = get_app_instance(request) view_obj.kwargs = {} view_obj.object_list = view_obj.get_queryset() view_obj.get_context_data(object_list=view_obj.object_list) self.assertEqual(view_obj.get_queryset().count(), 3) PARLER_FALLBACK = add_default_language_settings(PARLER_FALLBACK) # noqa: N806 with override_parler_settings(PARLER_LANGUAGES=PARLER_FALLBACK): view_obj = PostListView() request = self.get_page_request(pages[1], self.user, lang="fr", edit=True) view_obj.request = request view_obj.namespace, view_obj.config = get_app_instance(request) view_obj.kwargs = {} view_obj.object_list = view_obj.get_queryset() view_obj.get_context_data(object_list=view_obj.object_list) self.assertEqual(view_obj.get_queryset().count(), 0)
def test_author_entries_view(self): pages = self.get_pages() posts = self.get_posts() with smart_override("en"): request = self.get_page_request(pages[1], self.user, lang="en", edit=True) view_obj = AuthorEntriesView() view_obj.namespace, view_obj.config = get_app_instance(request) view_obj.request = request view_obj.kwargs = {"username": self.user.get_username()} qs = view_obj.get_queryset() self.assertEqual(qs.count(), 3) self.assertEqual(set(qs), {posts[0], posts[1], posts[2]}) view_obj.paginate_by = 1 view_obj.object_list = qs context = view_obj.get_context_data(object_list=view_obj.object_list) self.assertTrue(context["author"]) self.assertEqual(context["author"], self.user) self.assertTrue(context["is_paginated"]) self.assertEqual(list(context["post_list"]), [posts[0]]) self.assertEqual(context["paginator"].count, 3) self.assertEqual(context["post_list"][0].title, "First post") request = self.get_page_request(pages[1], self.user, edit=False) view_obj.request = request qs = view_obj.get_queryset() self.assertEqual(qs.count(), 1)
def test_taggedlist_view(self): pages = self.get_pages() posts = self.get_posts() posts[0].tags.add('tag 1', 'tag 2', 'tag 3', 'tag 4') posts[0].save() posts[1].tags.add('tag 6', 'tag 2', 'tag 5', 'tag 8') posts[1].save() with smart_override('en'): request = self.get_page_request(pages[1], self.user, lang='en', edit=True) view_obj = TaggedListView() view_obj.request = request view_obj.namespace, view_obj.config = get_app_instance(request) view_obj.kwargs = {'tag': 'tag-2'} qs = view_obj.get_queryset() self.assertEqual(qs.count(), 2) self.assertEqual(set(qs), set([posts[0], posts[1]])) view_obj.paginate_by = 1 view_obj.object_list = qs context = view_obj.get_context_data( object_list=view_obj.object_list) self.assertTrue(context['tagged_entries'], 'tag-2') self.assertTrue(context['is_paginated']) self.assertEqual(list(context['post_list']), [posts[0]]) self.assertEqual(context['paginator'].count, 2) self.assertEqual(context['post_list'][0].title, 'First post')
def test_menu_cache_clear_blogconfig(self): """ Tests if menu cache is cleared after config deletion """ from django.core.cache import cache from menus.models import CacheKey pages = self.get_pages() self.get_posts() self.reload_urlconf() app_config_test = BlogConfig.objects.create(namespace="test_config") app_config_test.app_title = "appx" app_config_test.object_name = "Blogx" app_config_test.save() lang = "en" with smart_override(lang): self._reset_menus() request = self.get_page_request(pages[1], self.user, pages[1].get_absolute_url(lang), edit=True) self.get_nodes(menu_pool, request) keys = CacheKey.objects.get_keys().distinct().values_list( "key", flat=True) self.assertTrue(cache.get_many(keys)) app_config_test.delete() self.assertFalse(cache.get_many(keys))
def create_from_imdb(cls, imdb_id): with smart_override('en'): movie, _ = cls._default_manager.get_or_create(imdb_id=imdb_id) movie.title = api_result['title'] movie.year = api_result['year'] movie.cover = Image.fetch_from_url(api_result['cover']) for lang, title in api_result['akas'].iteritems(): movie.set_current_language(lang) movie.title = title movie.save() for person in api_result['director']: director, _ = Person.objects.get_or_create(**person) director.is_director = True director.save() movie.directors.add(director) for pos, cast in enumerate(api_result['cast']): role = cast.pop('role', u'') actor, _ = Person.objects.get_or_create(**cast) actor.is_actor = True Cast.objects.create(order=pos, actor=actor, movie=movie, role=role) movie.save() return movie
def test_instant_articles(self): self.user.first_name = 'Admin' self.user.last_name = 'User' self.user.save() posts = self.get_posts() pages = self.get_pages() posts[0].tags.add('tag 1', 'tag 2', 'tag 3', 'tag 4') posts[0].categories.add(self.category_1) posts[0].author = self.user posts[0].save() add_plugin( posts[0].content, 'TextPlugin', language='en', body='<h3>Ciao</h3><p></p><p>Ciao</p>' ) with smart_override('en'): with switch_language(posts[0], 'en'): request = self.get_page_request( pages[1], self.user, path=posts[0].get_absolute_url() ) feed = FBInstantArticles() feed.namespace, feed.config = get_app_instance(request) self.assertEqual(list(feed.items()), [posts[0]]) xml = feed(request) self.assertContains(xml, '<guid>{0}</guid>'.format(posts[0].guid)) self.assertContains(xml, 'content:encoded') self.assertContains(xml, 'class="op-modified" datetime="{0}"'.format( posts[0].date_modified.strftime(FBInstantFeed.date_format) )) self.assertContains(xml, '<link rel="canonical" href="{0}"/>'.format( posts[0].get_full_url() )) # Assert text transformation self.assertContains(xml, '<h2>Ciao</h2><p>Ciao</p>') self.assertContains(xml, '<a>Admin User</a>')
def test_taggedlist_view(self): pages = self.get_pages() posts = self.get_posts() posts[0].tags.add("tag 1", "tag 2", "tag 3", "tag 4") posts[0].save() posts[1].tags.add("tag 6", "tag 2", "tag 5", "tag 8") posts[1].save() with smart_override("en"): request = self.get_page_request(pages[1], self.user, lang="en", edit=True) view_obj = TaggedListView() view_obj.request = request view_obj.namespace, view_obj.config = get_app_instance(request) view_obj.kwargs = {"tag": "tag-2"} qs = view_obj.get_queryset() self.assertEqual(qs.count(), 2) self.assertEqual(set(qs), {posts[0], posts[1]}) view_obj.paginate_by = 1 view_obj.object_list = qs context = view_obj.get_context_data(object_list=view_obj.object_list) self.assertTrue(context["tagged_entries"], "tag-2") self.assertTrue(context["is_paginated"]) self.assertEqual(list(context["post_list"]), [posts[0]]) self.assertEqual(context["paginator"].count, 2) self.assertEqual(context["post_list"][0].title, "First post")
def test_taggedlist_view(self): pages = self.get_pages() posts = self.get_posts() posts[0].tags.add('tag 1', 'tag 2', 'tag 3', 'tag 4') posts[0].save() posts[1].tags.add('tag 6', 'tag 2', 'tag 5', 'tag 8') posts[1].save() with smart_override('en'): request = self.get_page_request(pages[1], self.user, lang='en', edit=True) view_obj = TaggedListView() view_obj.request = request view_obj.namespace, view_obj.config = get_app_instance(request) view_obj.kwargs = {'tag': 'tag-2'} qs = view_obj.get_queryset() self.assertEqual(qs.count(), 2) self.assertEqual(set(qs), set([posts[0], posts[1]])) view_obj.paginate_by = 1 view_obj.object_list = qs context = view_obj.get_context_data(object_list=view_obj.object_list) self.assertTrue(context['tagged_entries'], 'tag-2') self.assertTrue(context['is_paginated']) self.assertEqual(list(context['post_list']), [posts[0]]) self.assertEqual(context['paginator'].count, 2) self.assertEqual(context['post_list'][0].title, 'First post')
def test_modifier(self): """ Tests if correct category is selected in the menu according to context (view object) """ posts = self.get_posts() pages = self.get_pages() tests = ( # view class, view kwarg, view object, category (PostDetailView, "slug", posts[0], posts[0].categories.first()), (CategoryEntriesView, "category", self.cats[2], self.cats[2]), ) for view_cls, kwarg, obj, cat in tests: request = self.get_page_request(pages[1], self.user, path=obj.get_absolute_url()) with smart_override("en"): with switch_language(obj, "en"): view_obj = view_cls() view_obj.request = request view_obj.namespace, view_obj.config = get_app_instance(request) view_obj.app_config = self.app_config_1 view_obj.kwargs = {kwarg: obj.slug} view_obj.get(request) # check if selected menu node points to cat nodes = menu_pool.get_nodes(request, namespace="BlogCategoryMenu") found = False for node in nodes: if node.selected: self.assertEqual(node.url, obj.get_absolute_url()) found = True break self.assertTrue(found)
def test_author_entries_view(self): posts = self.get_posts() pages = self.get_pages() with smart_override('en'): request = self.get_page_request(pages[1], self.user, lang='en', edit=True) view_obj = AuthorEntriesView() view_obj.namespace, view_obj.config = get_app_instance(request) view_obj.request = request view_obj.kwargs = {'username': self.user.get_username()} qs = view_obj.get_queryset() self.assertEqual(qs.count(), 3) self.assertEqual(set(qs), set([posts[0], posts[1], posts[2]])) view_obj.paginate_by = 1 view_obj.object_list = qs context = view_obj.get_context_data(object_list=view_obj.object_list) self.assertTrue(context['author']) self.assertEqual(context['author'], self.user) self.assertTrue(context['is_paginated']) self.assertEqual(list(context['post_list']), [posts[0]]) self.assertEqual(context['paginator'].count, 3) self.assertEqual(context['post_list'][0].title, 'First post') request = self.get_page_request(pages[1], self.user, edit=False) view_obj.request = request qs = view_obj.get_queryset() self.assertEqual(qs.count(), 1)
def test_post_archive_view(self): pages = self.get_pages() posts = self.get_posts() with smart_override('en'): request = self.get_page_request(pages[1], AnonymousUser(), lang='en', edit=False) view_obj = PostArchiveView() view_obj.request = request view_obj.namespace, view_obj.config = get_app_instance(request) view_obj.kwargs = {'year': now().year, 'month': now().month} # One post only, anonymous request qs = view_obj.get_queryset() self.assertEqual(qs.count(), 1) self.assertEqual(list(qs), [posts[0]]) view_obj.object_list = qs context = view_obj.get_context_data( object_list=view_obj.object_list) self.assertEqual( context['archive_date'].date(), now().replace(year=now().year, month=now().month, day=1).date())
def test_index_multilingual(self): self.index = ArticleIndex() content0 = self.rand_str(prefix='content0_') self.setup_categories() article_1 = self.create_article(content=content0, lead_in=u'lead in text', title=u'a title') article_2 = self.create_article(content=content0, lead_in=u'lead in text', title=u'second title') for article in (article_1, article_2): for category in (self.category1, self.category2): article.categories.add(category) with switch_language(article_2, 'de'): article_2.title = u'de title' article_2.lead_in = u'de lead in' article_2.save() LANGUAGES = add_default_language_settings(PARLER_LANGUAGES_HIDE) with override_parler_settings(PARLER_LANGUAGES=LANGUAGES): with smart_override('de'): language = get_current_language() # english-only article is excluded qs = self.index.index_queryset(language) self.assertEqual(qs.count(), 1) self.assertEqual( qs.translated(language, title__icontains='title').count(), 1) # the language is correctly setup for article_de in qs: self.assertEqual(self.index.get_title(article_de), 'de title') self.assertEqual(self.index.get_description(article_de), 'de lead in')
def test_instant_articles(self): self.user.first_name = "Admin" self.user.last_name = "User" self.user.save() pages = self.get_pages() posts = self.get_posts() posts[0].tags.add("tag 1", "tag 2", "tag 3", "tag 4") posts[0].categories.add(self.category_1) posts[0].author = self.user posts[0].save() add_plugin(posts[0].content, "TextPlugin", language="en", body="<h3>Ciao</h3><p></p><p>Ciao</p>") with smart_override("en"): with switch_language(posts[0], "en"): request = self.get_page_request(pages[1], self.user, path=posts[0].get_absolute_url()) feed = FBInstantArticles() feed.namespace, feed.config = get_app_instance(request) self.assertEqual(list(feed.items()), [posts[0]]) xml = feed(request) self.assertContains(xml, "<guid>{}</guid>".format(posts[0].guid)) self.assertContains(xml, "content:encoded") self.assertContains( xml, 'class="op-modified" datetime="{}"'.format( posts[0].date_modified.strftime(FBInstantFeed.date_format) ), ) self.assertContains(xml, '<link rel="canonical" href="{}"/>'.format(posts[0].get_full_url())) # Assert text transformation self.assertContains(xml, "<h2>Ciao</h2><p>Ciao</p>") self.assertContains(xml, "<a>Admin User</a>")
def test_author_entries_view(self): pages = self.get_pages() posts = self.get_posts() with smart_override('en'): request = self.get_page_request(pages[1], self.user, lang='en', edit=True) view_obj = AuthorEntriesView() view_obj.namespace, view_obj.config = get_app_instance(request) view_obj.request = request view_obj.kwargs = {'username': self.user.get_username()} qs = view_obj.get_queryset() self.assertEqual(qs.count(), 3) self.assertEqual(set(qs), set([posts[0], posts[1], posts[2]])) view_obj.paginate_by = 1 view_obj.object_list = qs context = view_obj.get_context_data( object_list=view_obj.object_list) self.assertTrue(context['author']) self.assertEqual(context['author'], self.user) self.assertTrue(context['is_paginated']) self.assertEqual(list(context['post_list']), [posts[0]]) self.assertEqual(context['paginator'].count, 3) self.assertEqual(context['post_list'][0].title, 'First post') request = self.get_page_request(pages[1], self.user, edit=False) view_obj.request = request qs = view_obj.get_queryset() self.assertEqual(qs.count(), 1)
def test_menu_nodes(self): """ Tests if all categories are present in the menu """ pages = self.get_pages() posts = self.get_posts() self.reload_urlconf() for lang in ('en', 'it'): with smart_override(lang): self._reset_menus() request = self.get_page_request( pages[1], self.user, pages[1].get_absolute_url(lang), edit=True) nodes = self.get_nodes(menu_pool, request) self.assertTrue( len(nodes), BlogCategory.objects.all().count() + len(pages)) nodes_url = set([node.get_absolute_url() for node in nodes]) cats_url = set([ cat.get_absolute_url() for cat in self.cats if cat.has_translation(lang) ]) self.assertTrue(cats_url.issubset(nodes_url)) self._reset_menus() posts[0].categories.clear() for lang in ('en', 'it'): with smart_override(lang): self._reset_menus() request = self.get_page_request( pages[1].get_draft_object(), self.user, pages[1].get_draft_object().get_absolute_url(lang)) nodes = self.get_nodes(menu_pool, request) urls = [node.get_absolute_url() for node in nodes] nodes_url = [node.get_absolute_url() for node in nodes] self.assertTrue( len(nodes_url), BlogCategory.objects.all().count() + len(pages)) self.assertFalse(posts[0].get_absolute_url(lang) in nodes_url) self.assertTrue(posts[1].get_absolute_url(lang) in nodes_url)
def test_non_existing_author_should_raise_404(self): pages = self.get_pages() with smart_override('en'): request = self.get_request(pages[1], 'en', AnonymousUser()) view_obj = AuthorEntriesView() view_obj.request = request view_obj.namespace, view_obj.config = get_app_instance(request) with self.assertRaises(Http404): view_obj.kwargs = {'username': '******'} view_obj.get_context_data()
def test_non_existing_blog_category_should_raise_404(self): pages = self.get_pages() with smart_override('en'): request = self.get_request(pages[1], 'en', AnonymousUser()) view_obj = CategoryEntriesView() view_obj.request = request view_obj.namespace, view_obj.config = get_app_instance(request) with self.assertRaises(Http404): view_obj.kwargs = {'category': 'unknown-category'} view_obj.get_queryset()
def render_item(self, contentitem): """ Render the individual item. May raise :class:`SkipItem` to ignore an item. """ render_language = get_render_language(contentitem) with smart_override(render_language): # Plugin output is likely HTML, but it should be placed in mark_safe() to raise awareness about escaping. # This is just like Django's Input.render() and unlike Node.render(). return contentitem.plugin._render_contentitem(self.request, contentitem)
def test_post_detail_view(self): pages = self.get_pages() posts = self.get_posts() with smart_override("en"): with switch_language(posts[0], "en"): request = self.get_page_request(pages[1], AnonymousUser(), lang="en", edit=False) view_obj = PostDetailView() view_obj.request = request view_obj.namespace, view_obj.config = get_app_instance(request) with self.assertRaises(Http404): view_obj.kwargs = {"slug": "not-existing"} post_obj = view_obj.get_object() view_obj.kwargs = {"slug": posts[0].slug} post_obj = view_obj.get_object() self.assertEqual(post_obj, posts[0]) self.assertEqual(post_obj.language_code, "en") with smart_override("it"): with switch_language(posts[0], "it"): request = self.get_page_request(pages[1], AnonymousUser(), lang="it", edit=False) view_obj = PostDetailView() view_obj.request = request view_obj.namespace, view_obj.config = get_app_instance(request) view_obj.kwargs = {"slug": posts[0].slug} post_obj = view_obj.get_object() self.assertEqual(post_obj, posts[0]) self.assertEqual(post_obj.language_code, "it") view_obj.object = post_obj context = view_obj.get_context_data() self.assertEqual(context["post"], posts[0]) self.assertEqual(context["post"].language_code, "it") self.assertTrue(context["meta"])
def test_post_detail_view(self): pages = self.get_pages() posts = self.get_posts() with smart_override('en'): with switch_language(posts[0], 'en'): request = self.get_page_request(pages[1], AnonymousUser(), lang='en', edit=False) view_obj = PostDetailView() view_obj.request = request view_obj.namespace, view_obj.config = get_app_instance(request) with self.assertRaises(Http404): view_obj.kwargs = {'slug': 'not-existing'} post_obj = view_obj.get_object() view_obj.kwargs = {'slug': posts[0].slug} post_obj = view_obj.get_object() self.assertEqual(post_obj, posts[0]) self.assertEqual(post_obj.language_code, 'en') with smart_override('it'): with switch_language(posts[0], 'it'): request = self.get_page_request(pages[1], AnonymousUser(), lang='it', edit=False) view_obj = PostDetailView() view_obj.request = request view_obj.namespace, view_obj.config = get_app_instance(request) view_obj.kwargs = {'slug': posts[0].slug} post_obj = view_obj.get_object() self.assertEqual(post_obj, posts[0]) self.assertEqual(post_obj.language_code, 'it') view_obj.object = post_obj context = view_obj.get_context_data() self.assertEqual(context['post'], posts[0]) self.assertEqual(context['post'].language_code, 'it') self.assertTrue(context['meta'])
def test_feed(self): self.user.first_name = 'Admin' self.user.last_name = 'User' self.user.save() pages = self.get_pages() posts = self.get_posts() posts[0].tags.add('tag 1', 'tag 2', 'tag 3', 'tag 4') posts[0].author = self.user posts[0].save() posts[1].tags.add('tag 6', 'tag 2', 'tag 5', 'tag 8') posts[1].save() posts[0].set_current_language('en') with smart_override('en'): with switch_language(posts[0], 'en'): request = self.get_page_request( pages[1], self.user, path=posts[0].get_absolute_url()) feed = LatestEntriesFeed() feed.namespace, feed.config = get_app_instance(request) self.assertEqual(list(feed.items()), [posts[0]]) self.reload_urlconf() xml = feed(request) self.assertContains(xml, posts[0].get_absolute_url()) self.assertContains(xml, 'Blog articles on example.com') self.assertContains(xml, 'Admin User</dc:creator>') with smart_override('it'): with switch_language(posts[0], 'it'): feed = LatestEntriesFeed() feed.namespace, feed.config = get_app_instance(request) self.assertEqual(list(feed.items()), [posts[0]]) request = self.get_page_request( pages[1], self.user, path=posts[0].get_absolute_url()) xml = feed(request) self.assertContains(xml, posts[0].get_absolute_url()) self.assertContains(xml, 'Articoli del blog su example.com') feed = TagFeed() feed.namespace = self.app_config_1.namespace feed.config = self.app_config_1 self.assertEqual(list(feed.items('tag-2')), [posts[0]])
def test_feed(self): self.user.first_name = "Admin" self.user.last_name = "User" self.user.save() pages = self.get_pages() posts = self.get_posts() posts[0].tags.add("tag 1", "tag 2", "tag 3", "tag 4") posts[0].author = self.user posts[0].save() posts[1].tags.add("tag 6", "tag 2", "tag 5", "tag 8") posts[1].save() posts[0].set_current_language("en") with smart_override("en"): with switch_language(posts[0], "en"): request = self.get_page_request( pages[1], self.user, path=posts[0].get_absolute_url()) feed = LatestEntriesFeed() feed.namespace, feed.config = get_app_instance(request) self.assertEqual(list(feed.items()), [posts[0]]) self.reload_urlconf() xml = feed(request) self.assertContains(xml, posts[0].get_absolute_url()) self.assertContains(xml, "Blog articles on example.com") self.assertContains(xml, "Admin User</dc:creator>") with smart_override("it"): with switch_language(posts[0], "it"): feed = LatestEntriesFeed() feed.namespace, feed.config = get_app_instance(request) self.assertEqual(list(feed.items()), [posts[0]]) request = self.get_page_request( pages[1], self.user, path=posts[0].get_absolute_url()) xml = feed(request) self.assertContains(xml, posts[0].get_absolute_url()) self.assertContains(xml, "Articoli del blog su example.com") feed = TagFeed() feed.namespace = self.app_config_1.namespace feed.config = self.app_config_1 self.assertEqual(list(feed.items("tag-2")), [posts[0]])
def test_feed(self): self.user.first_name = 'Admin' self.user.last_name = 'User' self.user.save() posts = self.get_posts() pages = self.get_pages() posts[0].tags.add('tag 1', 'tag 2', 'tag 3', 'tag 4') posts[0].author = self.user posts[0].save() posts[1].tags.add('tag 6', 'tag 2', 'tag 5', 'tag 8') posts[1].save() posts[0].set_current_language('en') with smart_override('en'): with switch_language(posts[0], 'en'): request = self.get_page_request(pages[1], self.user, path=posts[0].get_absolute_url()) feed = LatestEntriesFeed() feed.namespace, feed.config = get_app_instance(request) self.assertEqual(list(feed.items()), [posts[0]]) self.reload_urlconf() xml = feed(request) self.assertContains(xml, posts[0].get_absolute_url()) self.assertContains(xml, 'Blog articles on example.com') self.assertContains(xml, 'Admin User</dc:creator>') with smart_override('it'): with switch_language(posts[0], 'it'): feed = LatestEntriesFeed() feed.namespace, feed.config = get_app_instance(request) self.assertEqual(list(feed.items()), [posts[0]]) request = self.get_page_request(pages[1], self.user, path=posts[0].get_absolute_url()) xml = feed(request) self.assertContains(xml, posts[0].get_absolute_url()) self.assertContains(xml, 'Articoli del blog su example.com') feed = TagFeed() feed.namespace = self.app_config_1.namespace feed.config = self.app_config_1 self.assertEqual(list(feed.items('tag-2')), [posts[0]])
def test_model_attributes(self): self.get_pages() posts = self.get_posts() for language in posts[0].get_available_languages(): with smart_override(language): posts[0].set_current_language(language) knock_create = posts[0].as_knock(True) self.assertEqual(knock_create['title'], 'new {0}'.format(posts[0]._meta.verbose_name)) self.assertEqual(knock_create['message'], posts[0].title) self.assertEqual(knock_create['language'], language) for language in posts[0].get_available_languages(): with smart_override(language): posts[0].set_current_language(language) knock_create = posts[0].as_knock(False) self.assertEqual(knock_create['title'], 'new {0}'.format(posts[0]._meta.verbose_name)) self.assertEqual(knock_create['message'], posts[0].title) self.assertEqual(knock_create['language'], language)
def test_post_list_view_fallback(self): pages = self.get_pages() self.get_posts() PARLER_FALLBACK = { 1: ( { 'code': 'en' }, { 'code': 'it' }, { 'code': 'fr', 'hide_untranslated': True }, ), 'default': { 'fallback': 'en', 'hide_untranslated': False, } } with smart_override('fr'): view_obj = PostListView() request = self.get_page_request(pages[1], self.user, lang='fr', edit=True) view_obj.request = request view_obj.namespace, view_obj.config = get_app_instance(request) view_obj.kwargs = {} view_obj.object_list = view_obj.get_queryset() view_obj.get_context_data(object_list=view_obj.object_list) self.assertEqual(view_obj.get_queryset().count(), 3) PARLER_FALLBACK = add_default_language_settings(PARLER_FALLBACK) with override_parler_settings(PARLER_LANGUAGES=PARLER_FALLBACK): view_obj = PostListView() request = self.get_page_request(pages[1], self.user, lang='fr', edit=True) view_obj.request = request view_obj.namespace, view_obj.config = get_app_instance(request) view_obj.kwargs = {} view_obj.object_list = view_obj.get_queryset() view_obj.get_context_data(object_list=view_obj.object_list) self.assertEqual(view_obj.get_queryset().count(), 0)
def test_menu_nodes(self): """ Tests if all categories are present in the menu """ self.get_posts() self.get_pages() for lang in ("en", "it"): request = self.get_page_request(None, self.user, r"/%s/page-two/" % lang) with smart_override(lang): nodes = menu_pool.get_nodes(request, namespace="BlogCategoryMenu") nodes_url = set([node.url for node in nodes]) cats_url = set([cat.get_absolute_url() for cat in self.cats if cat.has_translation(lang)]) self.assertTrue(cats_url.issubset(nodes_url))
def test_post_detail_view(self): posts = self.get_posts() pages = self.get_pages() with smart_override('en'): with switch_language(posts[0], 'en'): request = self.get_page_request(pages[1], AnonymousUser(), lang='en', edit=False) view_obj = PostDetailView() view_obj.request = request view_obj.namespace, view_obj.config = get_app_instance(request) with self.assertRaises(Http404): view_obj.kwargs = {'slug': 'not-existing'} post_obj = view_obj.get_object() view_obj.kwargs = {'slug': posts[0].slug} post_obj = view_obj.get_object() self.assertEqual(post_obj, posts[0]) self.assertEqual(post_obj.language_code, 'en') with smart_override('it'): with switch_language(posts[0], 'it'): request = self.get_page_request(pages[1], AnonymousUser(), lang='it', edit=False) view_obj = PostDetailView() view_obj.request = request view_obj.namespace, view_obj.config = get_app_instance(request) view_obj.kwargs = {'slug': posts[0].slug} post_obj = view_obj.get_object() self.assertEqual(post_obj, posts[0]) self.assertEqual(post_obj.language_code, 'it') view_obj.object = post_obj context = view_obj.get_context_data() self.assertEqual(context['post'], posts[0]) self.assertEqual(context['post'].language_code, 'it') self.assertTrue(context['meta'])
def _get_category(self, data, category=None, lang='en'): data = deepcopy(data) for k, v in data.items(): if hasattr(v, '__call__'): data[k] = v() if not category: with smart_override(lang): data['app_config'] = self.app_configs[data['app_config']] category = BlogCategory.objects.create(**data) else: category.set_current_language(lang, initialize=True) for attr, val in data.items(): setattr(category, attr, val) category.save() return category
def _get_category(self, data, category=None, lang="en"): data = deepcopy(data) for k, v in data.items(): if callable(v): data[k] = v() if not category: with smart_override(lang): data["app_config"] = self.app_configs[data["app_config"]] category = BlogCategory.objects.create(**data) else: category.set_current_language(lang, initialize=True) for attr, val in data.items(): setattr(category, attr, val) category.save() return category
def test_templates(self): pages = self.get_pages() self.get_posts() with smart_override("en"): request = self.get_page_request(pages[1], self.user, edit=True) view_obj = PostListView() view_obj.request = request view_obj.namespace = self.app_config_1.namespace view_obj.config = self.app_config_1 self.assertEqual(view_obj.get_template_names(), os.path.join("djangocms_blog", "post_list.html")) self.app_config_1.app_data.config.template_prefix = "whatever" self.app_config_1.save() self.assertEqual(view_obj.get_template_names(), os.path.join("whatever", "post_list.html")) self.app_config_1.app_data.config.template_prefix = "" self.app_config_1.save()
def test_templates(self): posts = self.get_posts() pages = self.get_pages() with smart_override('en'): request = self.get_page_request(pages[1], self.user, edit=True) view_obj = PostListView() view_obj.request = request view_obj.namespace = self.app_config_1.namespace view_obj.config = self.app_config_1 self.assertEqual(view_obj.get_template_names(), os.path.join('djangocms_blog', 'post_list.html')) self.app_config_1.app_data.config.template_prefix = 'whatever' self.app_config_1.save() self.assertEqual(view_obj.get_template_names(), os.path.join('whatever', 'post_list.html')) self.app_config_1.app_data.config.template_prefix = '' self.app_config_1.save()
def test_sitemap(self): self.get_pages() posts = self.get_posts() posts[0].tags.add("tag 1", "tag 2", "tag 3", "tag 4") posts[0].save() posts[1].tags.add("tag 6", "tag 2", "tag 5", "tag 8") posts[1].publish = True posts[1].save() posts[0].set_current_language("en") sitemap = BlogSitemap() self.assertEqual(len(sitemap.items()), 6) for item in sitemap.items(): self.assertEqual(sitemap.lastmod(item).date(), now().date()) self.assertEqual(sitemap.priority(item), get_setting("SITEMAP_PRIORITY_DEFAULT")) self.assertEqual(sitemap.changefreq(item), get_setting("SITEMAP_CHANGEFREQ_DEFAULT")) with smart_override(item.get_current_language()): self.assertEqual(sitemap.location(item), item.get_absolute_url())
def test_post_archive_view(self): posts = self.get_posts() pages = self.get_pages() with smart_override('en'): request = self.get_page_request(pages[1], AnonymousUser(), lang='en', edit=False) view_obj = PostArchiveView() view_obj.request = request view_obj.namespace, view_obj.config = get_app_instance(request) view_obj.kwargs = {'year': now().year, 'month': now().month} # One post only, anonymous request qs = view_obj.get_queryset() self.assertEqual(qs.count(), 1) self.assertEqual(list(qs), [posts[0]]) view_obj.object_list = qs context = view_obj.get_context_data(object_list=view_obj.object_list) self.assertEqual(context['archive_date'].date(), now().replace(year=now().year, month=now().month, day=1).date())
def items(self): items = [] self.url_cache.clear() for lang in get_language_list(): self.url_cache[lang] = {} posts = Post.objects.translated(lang).language(lang).published() for post in posts: # check if the post actually has a url before appending # if a post is published but the associated app config is not # then this post will not have a url try: with smart_override(post.get_current_language()): self.url_cache[lang][post] = post.get_absolute_url() except NoReverseMatch: # couldn't determine the url of the post so pass on it continue items.append(post) return items
def test_menu_cache_clear_category(self): """ Tests if menu cache is cleared after category deletion """ from django.core.cache import cache from menus.models import CacheKey pages = self.get_pages() self.get_posts() self.reload_urlconf() lang = "en" with smart_override(lang): self._reset_menus() request = self.get_page_request(pages[1], self.user, pages[1].get_absolute_url(lang), edit=True) self.get_nodes(menu_pool, request) keys = CacheKey.objects.get_keys().distinct().values_list( "key", flat=True) self.assertTrue(cache.get_many(keys)) category_test = BlogCategory.objects.create( name="category test", app_config=self.app_config_1) category_test.set_current_language("it", initialize=True) category_test.name = "categoria test" category_test.save() self.assertFalse(cache.get_many(keys)) self.get_nodes(menu_pool, request) keys = CacheKey.objects.get_keys().distinct().values_list( "key", flat=True) self.assertTrue(cache.get_many(keys)) category_test.delete() self.assertFalse(cache.get_many(keys)) keys = CacheKey.objects.get_keys().distinct().values_list( "key", flat=True) self.assertFalse(keys)
def test_post_list_view_fallback(self): posts = self.get_posts() pages = self.get_pages() PARLER_FALLBACK = { 1: ( {'code': 'en'}, {'code': 'it'}, {'code': 'fr', 'hide_untranslated': True}, ), 'default': { 'fallback': 'en', 'hide_untranslated': False, } } with smart_override('fr'): view_obj = PostListView() request = self.get_page_request(pages[1], self.user, lang='fr', edit=True) view_obj.request = request view_obj.namespace, view_obj.config = get_app_instance(request) view_obj.kwargs = {} view_obj.object_list = view_obj.get_queryset() view_obj.get_context_data(object_list=view_obj.object_list) self.assertEqual(view_obj.get_queryset().count(), 3) PARLER_FALLBACK = add_default_language_settings(PARLER_FALLBACK) with override_parler_settings(PARLER_LANGUAGES=PARLER_FALLBACK): view_obj = PostListView() request = self.get_page_request(pages[1], self.user, lang='fr', edit=True) view_obj.request = request view_obj.namespace, view_obj.config = get_app_instance(request) view_obj.kwargs = {} view_obj.object_list = view_obj.get_queryset() view_obj.get_context_data(object_list=view_obj.object_list) self.assertEqual(view_obj.get_queryset().count(), 0)
def test_index_multilingual(self): self.index = ArticleIndex() content0 = self.rand_str(prefix='content0_') self.setup_categories() article_1 = self.create_article( content=content0, lead_in=u'lead in text', title=u'a title') article_2 = self.create_article( content=content0, lead_in=u'lead in text', title=u'second title') for article in (article_1, article_2): for tag_name in ('tag 1', 'tag2'): article.tags.add(tag_name) for category in (self.category1, self.category2): article.categories.add(category) with switch_language(article_2, 'de'): article_2.title = u'de title' article_2.lead_in = u'de lead in' article_2.save() LANGUAGES = add_default_language_settings(PARLER_LANGUAGES_HIDE) with override_parler_settings(PARLER_LANGUAGES=LANGUAGES): with smart_override('de'): language = get_current_language() # english-only article is excluded qs = self.index.index_queryset(language) self.assertEqual(qs.count(), 1) self.assertEqual( qs.translated(language, title__icontains='title').count(), 1 ) # the language is correctly setup for article_de in qs: self.assertEqual( self.index.get_title(article_de), 'de title') self.assertEqual( self.index.get_description(article_de), 'de lead in')
def test_sitemap(self): posts = self.get_posts() self.get_pages() posts[0].tags.add('tag 1', 'tag 2', 'tag 3', 'tag 4') posts[0].save() posts[1].tags.add('tag 6', 'tag 2', 'tag 5', 'tag 8') posts[1].publish = True posts[1].save() posts[0].set_current_language('en') sitemap = BlogSitemap() self.assertEqual(len(sitemap.items()), 6) for item in sitemap.items(): self.assertEqual(sitemap.lastmod(item).date(), now().date()) self.assertEqual( sitemap.priority(item), get_setting('SITEMAP_PRIORITY_DEFAULT') ) self.assertEqual( sitemap.changefreq(item), get_setting('SITEMAP_CHANGEFREQ_DEFAULT') ) with smart_override(item.get_current_language()): self.assertEqual( sitemap.location(item), item.get_absolute_url() )
def test_modifier(self): """ Tests if correct category is selected in the menu according to context (view object) """ posts = self.get_posts() pages = self.get_pages() tests = ( # view class, view kwarg, view object, category (PostDetailView, 'slug', posts[0], posts[0].categories.first()), (CategoryEntriesView, 'category', self.cats[2], self.cats[2]) ) self.app_config_1.app_data.config.menu_structure = MENU_TYPE_COMPLETE self.app_config_1.save() for view_cls, kwarg, obj, cat in tests: with smart_override('en'): with switch_language(obj, 'en'): request = self.get_page_request( pages[1], self.user, path=obj.get_absolute_url() ) cache.clear() menu_pool.clear(all=True) view_obj = view_cls() view_obj.request = request view_obj.namespace, view_obj.config = get_app_instance(request) view_obj.app_config = self.app_config_1 view_obj.kwargs = {kwarg: obj.slug} view_obj.get(request) view_obj.get_context_data() # check if selected menu node points to cat nodes = menu_pool.get_nodes(request) found = [] for node in nodes: if node.selected: found.append(node.get_absolute_url()) self.assertTrue(obj.get_absolute_url() in found) self.app_config_1.app_data.config.menu_structure = MENU_TYPE_CATEGORIES self.app_config_1.save() for view_cls, kwarg, obj, cat in tests: with smart_override('en'): with switch_language(obj, 'en'): request = self.get_page_request( pages[1], self.user, path=obj.get_absolute_url() ) cache.clear() menu_pool.clear(all=True) view_obj = view_cls() view_obj.request = request view_obj.namespace, view_obj.config = get_app_instance(request) view_obj.app_config = self.app_config_1 view_obj.kwargs = {kwarg: obj.slug} view_obj.get(request) view_obj.get_context_data() # check if selected menu node points to cat nodes = menu_pool.get_nodes(request) found = [] for node in nodes: if node.selected: found.append(node.get_absolute_url()) self.assertTrue(cat.get_absolute_url() in found) self.app_config_1.app_data.config.menu_structure = MENU_TYPE_COMPLETE self.app_config_1.save()
def test_menu_options(self): """ Tests menu structure based on menu_structure configuration """ self.get_pages() posts = self.get_posts() cats_url = {} posts_url = {} languages = ('en', 'it') for lang in languages: with smart_override(lang): cats_url[lang] = set([cat.get_absolute_url() for cat in self.cats if cat.has_translation(lang)]) posts_url[lang] = set([post.get_absolute_url(lang) for post in posts if post.has_translation(lang) and post.app_config == self.app_config_1]) # No item in the menu self.app_config_1.app_data.config.menu_structure = MENU_TYPE_NONE self.app_config_1.save() cache.clear() for lang in languages: request = self.get_page_request(None, self.user, r'/%s/page-two/' % lang) with smart_override(lang): nodes = menu_pool.get_nodes(request) nodes_url = set([node.url for node in nodes]) self.assertFalse(cats_url[lang].issubset(nodes_url)) self.assertFalse(posts_url[lang].issubset(nodes_url)) # Only posts in the menu self.app_config_1.app_data.config.menu_structure = MENU_TYPE_POSTS self.app_config_1.save() cache.clear() for lang in languages: request = self.get_page_request(None, self.user, r'/%s/page-two/' % lang) with smart_override(lang): nodes = menu_pool.get_nodes(request) nodes_url = set([node.url for node in nodes]) self.assertFalse(cats_url[lang].issubset(nodes_url)) self.assertTrue(posts_url[lang].issubset(nodes_url)) # Only categories in the menu self.app_config_1.app_data.config.menu_structure = MENU_TYPE_CATEGORIES self.app_config_1.save() cache.clear() for lang in languages: request = self.get_page_request(None, self.user, r'/%s/page-two/' % lang) with smart_override(lang): nodes = menu_pool.get_nodes(request) nodes_url = set([node.url for node in nodes]) self.assertTrue(cats_url[lang].issubset(nodes_url)) self.assertFalse(posts_url[lang].issubset(nodes_url)) # Both types in the menu self.app_config_1.app_data.config.menu_structure = MENU_TYPE_COMPLETE self.app_config_1.save() cache.clear() for lang in languages: request = self.get_page_request(None, self.user, r'/%s/page-two/' % lang) with smart_override(lang): nodes = menu_pool.get_nodes(request) nodes_url = set([node.url for node in nodes]) self.assertTrue(cats_url[lang].issubset(nodes_url)) self.assertTrue(posts_url[lang].issubset(nodes_url))
def location(self, obj): with smart_override(obj.get_current_language()): return self.url_cache[obj.get_current_language()][obj]
def test_modifier(self): """ Tests if correct category is selected in the menu according to context (view object) """ pages = self.get_pages() posts = self.get_posts() tests = ( # view class, view kwarg, view object, category (PostDetailView, 'slug', posts[0], posts[0].categories.first()), (CategoryEntriesView, 'category', self.cats[2], self.cats[2]) ) self.app_config_1.app_data.config.menu_structure = MENU_TYPE_COMPLETE self.app_config_1.save() for view_cls, kwarg, obj, cat in tests: with smart_override('en'): with switch_language(obj, 'en'): request = self.get_page_request( pages[1], self.user, path=obj.get_absolute_url() ) cache.clear() menu_pool.clear(all=True) view_obj = view_cls() view_obj.request = request view_obj.namespace, view_obj.config = get_app_instance(request) view_obj.app_config = self.app_config_1 view_obj.kwargs = {kwarg: obj.slug} view_obj.get(request) view_obj.get_context_data() # check if selected menu node points to cat nodes = menu_pool.get_nodes(request) found = [] for node in nodes: if node.selected: found.append(node.get_absolute_url()) self.assertTrue(obj.get_absolute_url() in found) self.app_config_1.app_data.config.menu_structure = MENU_TYPE_CATEGORIES self.app_config_1.save() for view_cls, kwarg, obj, cat in tests: with smart_override('en'): with switch_language(obj, 'en'): request = self.get_page_request( pages[1], self.user, path=obj.get_absolute_url() ) cache.clear() menu_pool.clear(all=True) view_obj = view_cls() view_obj.request = request view_obj.namespace, view_obj.config = get_app_instance(request) view_obj.app_config = self.app_config_1 view_obj.kwargs = {kwarg: obj.slug} view_obj.get(request) view_obj.get_context_data() # check if selected menu node points to cat nodes = menu_pool.get_nodes(request) found = [] for node in nodes: if node.selected: found.append(node.get_absolute_url()) self.assertTrue(cat.get_absolute_url() in found) self.app_config_1.app_data.config.menu_structure = MENU_TYPE_COMPLETE self.app_config_1.save()
def _render_items(request, placeholder, items, parent_object=None, template_name=None, cachable=False): edit_mode = is_edit_mode(request) item_output = {} output_ordering = [] all_cacheable = True all_timeout = DEFAULT_TIMEOUT placeholder_cache_name = "@global@" if placeholder is None else placeholder.slot if not hasattr(items, "non_polymorphic"): # The items is either a list of manually created items, or it's a QuerySet. # Can't prevent reading the subclasses only, so don't bother with caching here. remaining_items = items output_ordering = [item.pk or id(item) for item in items] else: # Unless it was done before, disable polymorphic effects. if not items.polymorphic_disabled: items = items.non_polymorphic() # First try to fetch all items non-polymorphic from memcache # If these are found, there is no need to query the derived data from the database. remaining_items = [] for i, contentitem in enumerate(items): output_ordering.append(contentitem.pk) output = None # Respect the cache output setting of the plugin if appsettings.FLUENT_CONTENTS_CACHE_OUTPUT: try: plugin = contentitem.plugin except PluginNotFound: pass else: if plugin.cache_output and contentitem.pk: output = plugin.get_cached_output(placeholder_cache_name, contentitem) all_timeout = _min_timeout(all_timeout, plugin.cache_timeout) # Support transition to new output format. if output is not None and not isinstance(output, ContentItemOutput): output = None logger.debug( "Flushed cached output of {0}#{1} to store new ContentItemOutput format (key: {2})".format( plugin.type_name, contentitem.pk, placeholder_cache_name ) ) # For debugging, ignore cached values when the template is updated. if output and settings.DEBUG: cachekey = get_rendering_cache_key(placeholder_cache_name, contentitem) if _is_template_updated(request, contentitem, cachekey): output = None if output: item_output[contentitem.pk] = output else: remaining_items.append(contentitem) # Fetch derived table data for all objects not found in memcached if remaining_items: remaining_items = items.get_real_instances(remaining_items) # See if the queryset contained anything. # This test is moved here, to prevent earlier query execution. if not items: placeholder_name = _get_placeholder_name(placeholder) logger.debug("- no items in placeholder '%s'", placeholder_name) return ContentItemOutput(mark_safe(u"<!-- no items in placeholder '{0}' -->".format(escape(placeholder_name)))) elif remaining_items: # Render remaining items for contentitem in remaining_items: try: plugin = contentitem.plugin except PluginNotFound as e: output = ContentItemOutput(mark_safe(u"<!-- error: {0} -->\n".format(str(e)))) logger.debug("- item #%s has no matching plugin: %s", contentitem.pk, str(e)) else: if plugin.render_ignore_item_language or (plugin.cache_output and plugin.cache_output_per_language): # Render the template in the current language. # The cache also stores the output under the current language code. # # It would make sense to apply this for fallback content too, # but that would be ambiguous however because the parent_object could also be a fallback, # and that case can't be detected here. Hence, better be explicit when desiring multi-lingual content. render_language = get_language() # Avoid switching the content, else: # Render the template in the ContentItem language. # This makes sure that {% trans %} tag output matches the language of the model field data. render_language = contentitem.language_code with smart_override(render_language): # Plugin output is likely HTML, but it should be placed in mark_safe() to raise awareness about escaping. # This is just like Django's Input.render() and unlike Node.render(). output = plugin._render_contentitem(request, contentitem) if ( appsettings.FLUENT_CONTENTS_CACHE_OUTPUT and plugin.cache_output and output.cacheable and contentitem.pk ): # Cache the output contentitem.plugin.set_cached_output(placeholder_cache_name, contentitem, output) else: # Item blocks caching the complete placeholder. all_cacheable = False if appsettings.FLUENT_CONTENTS_CACHE_OUTPUT: logger.debug("- item #%s is NOT cachable! Prevented by %r", contentitem.pk, plugin) if edit_mode: output.html = _wrap_contentitem_output(output.html, contentitem) item_id = contentitem.pk or id(contentitem) item_output[item_id] = output # Order all rendered items in the correct sequence. The derived tables could be truncated/reset, # so the base class model indexes don't necessary match with the derived indexes. Hence the dict + KeyError handling. # # The media is also collected in the same ordering, in case it's handled by django-compressor for example. output_ordered = [] merged_media = Media() for pk in output_ordering: try: output = item_output[pk] output_ordered.append(output.html) _add_media(merged_media, output.media) except KeyError: # The get_real_instances() didn't return an item for the derived table. This happens when either: # - that table is truncated/reset, while there is still an entry in the base ContentItem table. # A query at the derived table happens every time the page is being rendered. # - the model was completely removed which means there is also a stale ContentType object. item = next(item for item in items if item.pk == pk) try: class_name = item.plugin.type_name except PluginNotFound: # Derived table isn't there because the model has been removed. # There is a stale ContentType object, no plugin associated or loaded. class_name = "content type is stale" output_ordered.append( u"<!-- Missing derived model for ContentItem #{id}: {cls}. -->\n".format(id=pk, cls=class_name) ) logger.warning("Missing derived model for ContentItem #{id}: {cls}.".format(id=pk, cls=class_name)) pass # Combine all rendered items. Allow rendering the items with a template, # to inserting separators or nice start/end code. if not template_name: merged_output = mark_safe("".join(output_ordered)) else: context = { "contentitems": list(zip(items, output_ordered)), "parent_object": parent_object, # Can be None "edit_mode": edit_mode, } merged_output = render_to_string(template_name, context, context_instance=RequestContext(request)) # By default, cachable is False for templates. # Template name is ambiguous, can't reliable expire. # Nor can be determined whether the template is consistent or not cacheable. if not cachable: all_cacheable = False return ContentItemOutput(merged_output, merged_media, cacheable=all_cacheable, cache_timeout=all_timeout)
def _render_items(request, placeholder, items, parent_object=None, template_name=None): edit_mode = is_edit_mode(request) item_output = {} output_ordering = [] placeholder_cache_name = '@global@' if placeholder is None else placeholder.slot if not hasattr(items, "non_polymorphic"): # The items is either a list of manually created items, or it's a QuerySet. # Can't prevent reading the subclasses only, so don't bother with caching here. remaining_items = items output_ordering = [item.pk or id(item) for item in items] else: items = items.non_polymorphic() # First try to fetch all items non-polymorphic from memcache # If these are found, there is no need to query the derived data from the database. remaining_items = [] for i, contentitem in enumerate(items): output_ordering.append(contentitem.pk) output = None try: # Respect the cache output setting of the plugin if appsettings.FLUENT_CONTENTS_CACHE_OUTPUT and contentitem.plugin.cache_output and contentitem.pk: output = contentitem.plugin.get_cached_output(placeholder_cache_name, contentitem) # Support transition to new output format. if not isinstance(output, ContentItemOutput): output = None logger.debug("Flushed cached output of {0}#{1} to store new format (key: {2}) ".format(contentitem.plugin.type_name, contentitem.pk, placeholder_cache_name)) except PluginNotFound: pass # For debugging, ignore cached values when the template is updated. if output and settings.DEBUG: cachekey = get_rendering_cache_key(placeholder_cache_name, contentitem) if _is_template_updated(request, contentitem, cachekey): output = None if output: item_output[contentitem.pk] = output else: remaining_items.append(contentitem) # Fetch derived table data for all objects not found in memcached if remaining_items: remaining_items = items.get_real_instances(remaining_items) # See if the queryset contained anything. # This test is moved here, to prevent earlier query execution. if not items: return ContentItemOutput(mark_safe(u"<!-- no items in placeholder '{0}' -->".format(escape(_get_placeholder_name(placeholder))))) elif remaining_items: # Render remaining items for contentitem in remaining_items: try: plugin = contentitem.plugin except PluginNotFound as e: output = ContentItemOutput(mark_safe(u'<!-- error: {0} -->\n'.format(str(e)))) else: # Always try to render the template in the ContentItem language. # This makes sure that {% trans %} tags function properly if the language happens to be different. with smart_override(contentitem.language_code): # Plugin output is likely HTML, but it should be placed in mark_safe() to raise awareness about escaping. # This is just like Django's Input.render() and unlike Node.render(). output = plugin._render_contentitem(request, contentitem) if appsettings.FLUENT_CONTENTS_CACHE_OUTPUT and plugin.cache_output and contentitem.pk: contentitem.plugin.set_cached_output(placeholder_cache_name, contentitem, output) if edit_mode: output.html = _wrap_contentitem_output(output.html, contentitem) item_id = contentitem.pk or id(contentitem) item_output[item_id] = output # Order all rendered items in the correct sequence. The derived tables could be truncated/reset, # so the base class model indexes don't necessary match with the derived indexes. Hence the dict + KeyError handling. # # The media is also collected in the same ordering, in case it's handled by django-compressor for example. output_ordered = [] merged_media = Media() for pk in output_ordering: try: output = item_output[pk] output_ordered.append(output.html) _add_media(merged_media, output.media) except KeyError: # The get_real_instances() didn't return an item for the derived table. This happens when either: # - that table is truncated/reset, while there is still an entry in the base ContentItem table. # A query at the derived table happens every time the page is being rendered. # - the model was completely removed which means there is also a stale ContentType object. item = next(item for item in items if item.pk == pk) try: class_name = item.plugin.type_name except PluginNotFound: # Derived table isn't there because the model has been removed. # There is a stale ContentType object, no plugin associated or loaded. class_name = 'content type is stale' output_ordered.append(u"<!-- Missing derived model for ContentItem #{id}: {cls}. -->\n".format(id=pk, cls=class_name)) logger.warning("Missing derived model for ContentItem #{id}: {cls}.".format(id=pk, cls=class_name)) pass # Combine all rendered items. Allow rendering the items with a template, # to inserting separators or nice start/end code. if not template_name: merged_output = mark_safe(''.join(output_ordered)) else: context = { 'contentitems': list(zip(items, output_ordered)), 'parent_object': parent_object, # Can be None 'edit_mode': edit_mode, } merged_output = render_to_string(template_name, context, context_instance=RequestContext(request)) return ContentItemOutput(merged_output, merged_media)
def test_post_list_view(self): pages = self.get_pages() posts = self.get_posts() request = self.get_request(pages[1], 'en', AnonymousUser()) with smart_override('en'): view_obj = PostListView() view_obj.request = request view_obj.namespace, view_obj.config = get_app_instance(request) self.assertEqual(getattr(request, BLOG_CURRENT_NAMESPACE, None), None) self.assertEqual(list(view_obj.get_queryset()), [posts[0]]) self.assertEqual(getattr(request, BLOG_CURRENT_NAMESPACE), self.app_config_1) request = self.get_page_request(pages[1], self.user, lang='en', edit=False) view_obj.namespace, view_obj.config = get_app_instance(request) view_obj.request = request view_obj.kwargs = {} qs = view_obj.get_queryset() self.assertEqual(qs.count(), 1) self.assertEqual(set(qs), set([posts[0]])) request = self.get_page_request(pages[1], self.user, lang='en', edit=True) view_obj.namespace, view_obj.config = get_app_instance(request) view_obj.request = request self.assertEqual(set(view_obj.get_queryset()), set([posts[0], posts[1], posts[2]])) view_obj.kwargs = {} view_obj.args = () view_obj.object_list = view_obj.get_queryset() view_obj.paginate_by = 1 context = view_obj.get_context_data( object_list=view_obj.object_list) self.assertTrue(context['is_paginated']) self.assertEqual(list(context['post_list']), [posts[0]]) self.assertEqual(context['paginator'].count, 3) self.assertEqual(context['post_list'][0].title, 'First post') response = view_obj.render_to_response(context) self.assertContains(response, context['post_list'][0].get_absolute_url()) self.assertEqual(getattr(request, BLOG_CURRENT_NAMESPACE), self.app_config_1) posts[1].sites.add(self.site_2) self.assertTrue(view_obj.get_queryset().count(), 2) self.assertFalse(posts[1] in view_obj.get_queryset()) with smart_override('it'): request = self.get_page_request(pages[1], self.user, lang='it', edit=True) view_obj = PostListView() view_obj.namespace, view_obj.config = get_app_instance(request) view_obj.request = request view_obj.args = () view_obj.kwargs = {} view_obj.object_list = view_obj.get_queryset() context = view_obj.get_context_data( object_list=view_obj.object_list) self.assertEqual(context['post_list'][0].title, 'Primo post') response = view_obj.render_to_response(context) self.assertContains(response, context['post_list'][0].get_absolute_url()) blog_menu = request.toolbar.get_or_create_menu( 'djangocms_blog', _('Blog')) self.assertEqual(len(blog_menu.items), 3) self.assertEqual( len( blog_menu.find_items( ModalItem, url=reverse('admin:djangocms_blog_post_changelist'))), 1) self.assertEqual( len( blog_menu.find_items( ModalItem, url=reverse('admin:djangocms_blog_post_add'))), 1) self.assertEqual( len( blog_menu.find_items( ModalItem, url=reverse('admin:djangocms_blog_blogconfig_change', args=(self.app_config_1.pk, )))), 1)
def location(self, obj): with smart_override(obj.get_current_language()): return obj.get_absolute_url(obj.get_current_language())
def test_post_list_view(self): posts = self.get_posts() pages = self.get_pages() request = self.get_request(pages[1], 'en', AnonymousUser()) with smart_override('en'): view_obj = PostListView() view_obj.request = request view_obj.namespace, view_obj.config = get_app_instance(request) self.assertEqual(getattr(request, BLOG_CURRENT_NAMESPACE, None), None) self.assertEqual(list(view_obj.get_queryset()), [posts[0]]) self.assertEqual(getattr(request, BLOG_CURRENT_NAMESPACE), self.app_config_1) request = self.get_page_request(pages[1], self.user, lang='en', edit=False) view_obj.namespace, view_obj.config = get_app_instance(request) view_obj.request = request view_obj.kwargs = {} qs = view_obj.get_queryset() self.assertEqual(qs.count(), 1) self.assertEqual(set(qs), set([posts[0]])) request = self.get_page_request(pages[1], self.user, lang='en', edit=True) view_obj.namespace, view_obj.config = get_app_instance(request) view_obj.request = request self.assertEqual(set(view_obj.get_queryset()), set([posts[0], posts[1], posts[2]])) view_obj.kwargs = {} view_obj.args = () view_obj.object_list = view_obj.get_queryset() view_obj.paginate_by = 1 context = view_obj.get_context_data(object_list=view_obj.object_list) self.assertTrue(context['is_paginated']) self.assertEqual(list(context['post_list']), [posts[0]]) self.assertEqual(context['paginator'].count, 3) self.assertEqual(context['post_list'][0].title, 'First post') response = view_obj.render_to_response(context) self.assertContains(response, context['post_list'][0].get_absolute_url()) self.assertEqual(getattr(request, BLOG_CURRENT_NAMESPACE), self.app_config_1) posts[1].sites.add(self.site_2) self.assertTrue(view_obj.get_queryset().count(), 2) self.assertFalse(posts[1] in view_obj.get_queryset()) with smart_override('it'): request = self.get_page_request(pages[1], self.user, lang='it', edit=True) view_obj = PostListView() view_obj.namespace, view_obj.config = get_app_instance(request) view_obj.request = request view_obj.args = () view_obj.kwargs = {} view_obj.object_list = view_obj.get_queryset() context = view_obj.get_context_data(object_list=view_obj.object_list) self.assertEqual(context['post_list'][0].title, 'Primo post') response = view_obj.render_to_response(context) self.assertContains(response, context['post_list'][0].get_absolute_url()) blog_menu = request.toolbar.get_or_create_menu('djangocms_blog', _('Blog')) self.assertEqual(len(blog_menu.items), 3) self.assertEqual(len(blog_menu.find_items( ModalItem, url=reverse('admin:djangocms_blog_post_changelist') )), 1) self.assertEqual(len(blog_menu.find_items( ModalItem, url=reverse('admin:djangocms_blog_post_add') )), 1) self.assertEqual(len(blog_menu.find_items( ModalItem, url=reverse( 'admin:djangocms_blog_blogconfig_change', args=(self.app_config_1.pk,) ) )), 1)
def test_menu_options(self): """ Tests menu structure based on menu_structure configuration """ posts = self.get_posts() self.get_pages() cats_url = {} posts_url = {} languages = ('en', 'it') for lang in languages: with smart_override(lang): cats_url[lang] = set([cat.get_absolute_url() for cat in self.cats if cat.has_translation(lang)]) posts_url[lang] = set([post.get_absolute_url() for post in posts if post.has_translation(lang) and post.app_config == self.app_config_1]) # No item in the menu self.app_config_1.app_data.config.menu_structure = MENU_TYPE_NONE self.app_config_1.save() cache.clear() for lang in languages: request = self.get_page_request(None, self.user, r'/%s/page-two/' % lang) with smart_override(lang): nodes = menu_pool.get_nodes(request) nodes_url = set([node.url for node in nodes]) self.assertFalse(cats_url[lang].issubset(nodes_url)) self.assertFalse(posts_url[lang].issubset(nodes_url)) # Only posts in the menu self.app_config_1.app_data.config.menu_structure = MENU_TYPE_POSTS self.app_config_1.save() cache.clear() for lang in languages: request = self.get_page_request(None, self.user, r'/%s/page-two/' % lang) with smart_override(lang): nodes = menu_pool.get_nodes(request) nodes_url = set([node.url for node in nodes]) self.assertFalse(cats_url[lang].issubset(nodes_url)) self.assertTrue(posts_url[lang].issubset(nodes_url)) # Only categories in the menu self.app_config_1.app_data.config.menu_structure = MENU_TYPE_CATEGORIES self.app_config_1.save() cache.clear() for lang in languages: request = self.get_page_request(None, self.user, r'/%s/page-two/' % lang) with smart_override(lang): nodes = menu_pool.get_nodes(request) nodes_url = set([node.url for node in nodes]) self.assertTrue(cats_url[lang].issubset(nodes_url)) self.assertFalse(posts_url[lang].issubset(nodes_url)) # Both types in the menu self.app_config_1.app_data.config.menu_structure = MENU_TYPE_COMPLETE self.app_config_1.save() cache.clear() for lang in languages: request = self.get_page_request(None, self.user, r'/%s/page-two/' % lang) with smart_override(lang): nodes = menu_pool.get_nodes(request) nodes_url = set([node.url for node in nodes]) self.assertTrue(cats_url[lang].issubset(nodes_url)) self.assertTrue(posts_url[lang].issubset(nodes_url))
def get_translated_url(context, lang_code, object=None): """ Get the proper URL for this page in a different language. Note that this algorithm performs a "best effect" approach to give a proper URL. To make sure the proper view URL is returned, add the :class:`~parler.views.ViewUrlMixin` to your view. Example, to build a language menu:: <ul> {% for lang_code, title in LANGUAGES %} {% get_language_info for lang_code as lang %} {% get_translated_url lang_code as tr_url %} {% if tr_url %}<li{% if lang_code == LANGUAGE_CODE %} class="is-selected"{% endif %}><a href="{{ tr_url }}" hreflang="{{ lang_code }}">{{ lang.name_local|capfirst }}</a></li>{% endif %} {% endfor %} </ul> Or to inform search engines about the translated pages:: {% for lang_code, title in LANGUAGES %} {% get_translated_url lang_code as tr_url %} {% if tr_url %}<link rel="alternate" hreflang="{{ lang_code }}" href="{{ tr_url }}" />{% endif %} {% endfor %} Note that using this tag is not thread-safe if the object is shared between threads. It temporary changes the current language of the view object. """ view = context.get('view', None) if object is None: # Try a few common object variables, the SingleObjectMixin object, # The Django CMS "current_page" variable, or the "page" from django-fluent-pages and Mezzanine. # This makes this tag work with most CMSes out of the box. object = context.get('object', None) \ or context.get('current_page', None) \ or context.get('page', None) try: if view is not None: # Allow a view to specify what the URL should be. # This handles situations where the slug might be translated, # and gives you complete control over the results of this template tag. get_view_url = getattr(view, 'get_view_url', None) if get_view_url: with smart_override(lang_code): return view.get_view_url() # Now, the "best effort" part starts. # See if it's a DetailView that exposes the object. if object is None: object = getattr(view, 'object', None) if object is not None and hasattr(object, 'get_absolute_url'): # There is an object, get the URL in the different language. # NOTE: this *assumes* that there is a detail view, not some edit view. # In such case, a language menu would redirect a user from the edit page # to a detail page; which is still way better a 404 or homepage. if isinstance(object, TranslatableModel): # Need to handle object URL translations. # Just using smart_override() should be enough, as a translated object # should use `switch_language(self)` internally before returning an URL. # However, it doesn't hurt to help a bit here. with switch_language(object, lang_code): return object.get_absolute_url() else: # Always switch the language before resolving, so i18n_patterns() are supported. with smart_override(lang_code): return object.get_absolute_url() except TranslationDoesNotExist: # Typically projects have a fallback language, so even unknown languages will return something. # This either means fallbacks are disabled, or the fallback language is not found! return '' # Just reverse the current URL again in a new language, and see where we end up. # This doesn't handle translated slugs, but will resolve to the proper view name. path = context['request'].path try: resolvermatch = resolve(path) except Resolver404: # Can't resolve the page itself, the page is apparently a 404. # This can also happen for the homepage in an i18n_patterns situation. return '' with smart_override(lang_code): clean_kwargs = _cleanup_urlpattern_kwargs(resolvermatch.kwargs) return reverse(resolvermatch.view_name, args=resolvermatch.args, kwargs=clean_kwargs)