def test_app_reverse_multiple(self): """ The app_reverse functions should support multiple mount points for an app. """ shop2 = WebShopPage.objects.create(title="Shop2", slug="shop2", status=WebShopPage.PUBLISHED, author=self.user) self.assertEqual(WebShopPage.objects.published().count(), 2) # There are now 2 mount points, the functions should detect that self.assertRaises(MultipleReverseMatch, lambda: app_reverse('webshop_index')) self.assertRaises(MultipleReverseMatch, lambda: mixed_reverse('webshop_index')) # The functions have a 'current_page' parameter that allows relative resolving. # This is designed for template functions, to allow resolving relative to the current page node. self.assertEqual(app_reverse('webshop_index', current_page=shop2), '/shop2/') self.assertEqual( app_reverse('webshop_article', current_page=shop2, kwargs={'slug': 'foobar'}), '/shop2/foobar/') self.assertEqual(mixed_reverse('webshop_index', current_page=shop2), '/shop2/') self.assertEqual( mixed_reverse('webshop_article', current_page=shop2, kwargs={'slug': 'foobar'}), '/shop2/foobar/')
def test_mixed_reverse_standalone(self): """ When a custom app is not hooked via the CMS page tree, mixed_reverse() should still work. """ self.assertRaises(PageTypeNotMounted, lambda: app_reverse('webshop_index')) self.assertEqual(mixed_reverse('webshop_index'), '/') self.assertEqual(mixed_reverse('webshop_article', kwargs={'slug': 'foobar'}), '/foobar/')
def test_app_reverse(self): """ The app_reverse function should find the proper CMS page where the app is mounted. """ self.assertEqual(app_reverse('webshop_index'), '/shop/') self.assertEqual(app_reverse('webshop_article', kwargs={'slug': 'foobar'}), '/shop/foobar/') self.assertEqual(mixed_reverse('webshop_index'), '/shop/') self.assertEqual(mixed_reverse('webshop_article', kwargs={'slug': 'foobar'}), '/shop/foobar/')
def test_app_reverse(self): """ The app_reverse function should find the proper CMS page where the app is mounted. """ self.assertEqual(WebShopPage.objects.published().count(), 1) self.assertEqual(app_reverse('webshop_index'), '/shop/') self.assertEqual(app_reverse('webshop_article', kwargs={'slug': 'foobar'}), '/shop/foobar/') self.assertEqual(mixed_reverse('webshop_index'), '/shop/') self.assertEqual(mixed_reverse('webshop_article', kwargs={'slug': 'foobar'}), '/shop/foobar/')
def get_value(self, context, *tag_args, **tag_kwargs): view_name = tag_args[0] url_args = tag_args[1::] url_kwargs = dict([(smart_str(name, 'ascii'), value) for name, value in iteritems(tag_kwargs)]) # The app_reverse() tag can handle multiple results fine if it knows what the current page is. # Try to find it. request = context.get('request') page = getattr(request, '_current_fluent_page', None) if not page: # There might be a 'page' variable, that was retrieved via `{% get_fluent_page_vars %}`. # However, django-haystack also uses this variable name, so check whether it's the correct object. page = context.get('page') if not isinstance(page, UrlNode): page = None if django.VERSION >= (1, 8): # request.current_app is passed everywhere if available, otherwise it does not exist. # Somehow it needs to be assigned explicitly in the app # via: request.current_app = request.resolver_match.namespace current_app = getattr(request, 'current_app', None) else: current_app = context.current_app # Try a normal URLConf URL, then an app URL return mixed_reverse(view_name, args=url_args, kwargs=url_kwargs, current_app=current_app, current_page=page)
def get_value(self, context, *tag_args, **tag_kwargs): view_name = tag_args[0] url_args = tag_args[1::] url_kwargs = dict([(smart_str(name, 'ascii'), value) for name, value in iteritems(tag_kwargs)]) # The app_reverse() tag can handle multiple results fine if it knows what the current page is. # Try to find it. request = context.get('request') page = getattr(request, '_current_fluent_page', None) if not page: # There might be a 'page' variable, that was retrieved via `{% get_fluent_page_vars %}`. # However, django-haystack also uses this variable name, so check whether it's the correct object. page = context.get('page') if not isinstance(page, UrlNode): page = None # request.current_app is passed everywhere if available, otherwise it does not exist. # Somehow it needs to be assigned explicitly in the app # via: request.current_app = request.resolver_match.namespace current_app = getattr(request, 'current_app', None) # Try a normal URLConf URL, then an app URL return mixed_reverse(view_name, args=url_args, kwargs=url_kwargs, current_app=current_app, current_page=page)
def faq_reverse(viewname, args=None, kwargs=None, current_app='fluent_faq', current_page=None, language_code=None, multiple=False, ignore_multiple=False): """ Reverse a URL to the blog, taking various configuration options into account. This is a compatibility function to allow django-fluent-faq to operate stand-alone. Either the app can be hooked in the URLconf directly, or it can be added as a pagetype of *django-fluent-pages*. """ if _HAS_FLUENT_PAGES: return mixed_reverse(viewname, args=args, kwargs=kwargs, current_page=current_page, language_code=language_code, multiple=multiple, ignore_multiple=ignore_multiple) else: return reverse(viewname, args=args, kwargs=kwargs, current_app=current_app)
def blog_reverse( viewname, args=None, kwargs=None, current_app="fluent_blogs", current_page=None, multiple=False, ignore_multiple=False, ): """ Reverse a URL to the blog, taking various configuration options into account. This is a compatibility function to allow django-fluent-blogs to operate stand-alone. Either the app can be hooked in the URLconf directly, or it can be added as a pagetype of *django-fluent-pages*. """ if _HAS_FLUENT_PAGES: return mixed_reverse( viewname, args=args, kwargs=kwargs, current_page=current_page, multiple=multiple, ignore_multiple=ignore_multiple, ) else: return reverse(viewname, args=args, kwargs=kwargs, current_app=current_app)
def test_app_reverse_unmounted(self): """ The app_reverse functions should raise an exception when the pagetype is not added in the page tree. """ for page in WebShopPage.objects.all(): page.delete() # Allow signals to be sent, and clear caches self.assertRaises(PageTypeNotMounted, lambda: app_reverse('webshop_index')) self.assertRaises(PageTypeNotMounted, lambda: mixed_reverse('webshop_index'))
def test_app_reverse_multiple(self): """ The app_reverse functions should support multiple mount points for an app. """ shop2 = WebShopPage.objects.create(title="Shop2", slug="shop2", status=WebShopPage.PUBLISHED, author=self.user) # There are now 2 mount points, the functions should detect that self.assertRaises(MultipleReverseMatch, lambda: app_reverse('webshop_index')) self.assertRaises(MultipleReverseMatch, lambda: mixed_reverse('webshop_index')) # The functions have a 'current_page' parameter that allows relative resolving. # This is designed for template functions, to allow resolving relative to the current page node. self.assertEqual(app_reverse('webshop_index', current_page=shop2), '/shop2/') self.assertEqual(app_reverse('webshop_article', current_page=shop2, kwargs={'slug': 'foobar'}), '/shop2/foobar/') self.assertEqual(mixed_reverse('webshop_index', current_page=shop2), '/shop2/') self.assertEqual(mixed_reverse('webshop_article', current_page=shop2, kwargs={'slug': 'foobar'}), '/shop2/foobar/')
def test_app_reverse_unmounted(self): """ The app_reverse functions should raise an exception when the pagetype is not added in the page tree. """ for page in WebShopPage.objects.all(): page.delete() # Allow signals to be sent, and clear caches self.assertEqual(WebShopPage.objects.published().count(), 0) self.assertRaises(PageTypeNotMounted, lambda: app_reverse('webshop_index')) self.assertRaises(PageTypeNotMounted, lambda: mixed_reverse('webshop_index'))
def render_tag(self, context, *tag_args, **tag_kwargs): view_name = tag_args[0] url_args = tag_args[1::] url_kwargs = dict([(smart_str(name, 'ascii'), value) for name, value in tag_kwargs.items()]) # If the page is a UrlNode, use it as base for the pages. page = context.get('page') if not isinstance(page, UrlNode): page = None # Try a normal URLConf URL, then an app URL return mixed_reverse(view_name, args=url_args, kwargs=url_kwargs, current_app=context.current_app, current_page=page)
def get_view_url(self): """ When using the :attr:`ViewUrlMixin.view_url_name <parler.views.ViewUrlMixin.view_url_name>` feature of *django-parler*, this makes sure that mounted pages are also supported. It uses :func:`fluent_pages.urlresolvers.mixed_reverse` function to resolve the :attr:`view_url_name`. """ # This method is used by the ``get_translated_url`` template tag of django-parler if self.view_url_name: return mixed_reverse(self.view_url_name, args=self.args, kwargs=self.kwargs, current_page=self.get_current_page()) else: return super(CurrentPageMixin, self).get_view_url()
def render(self, context): # If the page is a UrlNode, use it as base for the pages. page = context['page'] if not isinstance(page, UrlNode): page = None view_name = self.name_expr.resolve(context) args = [arg.resolve(context) for arg in self.args] kwargs = dict([(smart_str(k, 'ascii'), v.resolve(context)) for k, v in self.kwargs.items()]) # Try a normal URLConf URL, then an app URL return mixed_reverse(view_name, args=args, kwargs=kwargs, current_app=context.current_app, current_page=page)
def render_change_form(self, request, context, add=False, change=False, form_url='', obj=None): # When the page is accessed via a pagetype, warn that the node can't be previewed yet. context['preview_error'] = '' if 'fluent_pages' in settings.INSTALLED_APPS: from fluent_pages.urlresolvers import mixed_reverse, PageTypeNotMounted, MultipleReverseMatch try: mixed_reverse('entry_archive_index') except PageTypeNotMounted: from fluent_blogs.pagetypes.blogpage.models import BlogPage context['preview_error'] = ugettext("The blog entry can't be previewed yet, a '{page_type_name}' page needs to be created first.").format(page_type_name=BlogPage._meta.verbose_name) except MultipleReverseMatch: # When 'entry_archive_index is ambiguous (because there are multiple blog nodes in the fluent-pages tree), # the edit page will automatically pick an option. pass except NoReverseMatch: # Since forgetting the pagetype app is easy, give off a warning to help developers # find their way with these apps. raise ImproperlyConfigured( "To use django-fluent-blogs, either include('fluent_blogs.urls') in the URLConf, " "or add the 'fluent_blogs.pagetypes.blogpage' app to the INSTALLED_APPS." ) return super(AbstractEntryBaseAdmin, self).render_change_form(request, context, add, change, form_url, obj)
def render_tag(self, context, *tag_args, **tag_kwargs): view_name = tag_args[0] url_args = tag_args[1::] url_kwargs = dict([(smart_str(name, 'ascii'), value) for name, value in iter(tag_kwargs.items())]) # The app_reverse() tag can handle multiple results fine if it knows what the current page is. # Try to find it. request = context.get('request') page = getattr(request, '_current_fluent_page', None) if not page: # There might be a 'page' variable, that was retrieved via `{% get_fluent_page_vars %}`. # However, django-haystack also uses this variable name, so check whether it's the correct object. page = context.get('page') if not isinstance(page, UrlNode): page = None # Try a normal URLConf URL, then an app URL return mixed_reverse(view_name, args=url_args, kwargs=url_kwargs, current_app=context.current_app, current_page=page)
def render_tag(self, context, *tag_args, **tag_kwargs): view_name = tag_args[0] url_args = tag_args[1::] url_kwargs = dict([(smart_str(name, 'ascii'), value) for name, value in iteritems(tag_kwargs)]) # The app_reverse() tag can handle multiple results fine if it knows what the current page is. # Try to find it. request = context.get('request') page = getattr(request, '_current_fluent_page', None) if not page: # There might be a 'page' variable, that was retrieved via `{% get_fluent_page_vars %}`. # However, django-haystack also uses this variable name, so check whether it's the correct object. page = context.get('page') if not isinstance(page, UrlNode): page = None # Try a normal URLConf URL, then an app URL return mixed_reverse(view_name, args=url_args, kwargs=url_kwargs, current_app=context.current_app, current_page=page)
def _reverse_blogpage_index(self, request, obj=None): # Updated mixed_reverse() call, with language code included. from fluent_pages.urlresolvers import mixed_reverse language_code = self.get_form_language(request, obj) return mixed_reverse('entry_archive_index', language_code=language_code)
def _reverse_blogpage_index(self, request, obj=None): # Internal method with "protected access" to handle translation differences. # This is only called when 'fluent_pages' is in the INSTALLED_APPS. from fluent_pages.urlresolvers import mixed_reverse return mixed_reverse('entry_archive_index')
def _reverse_faqpage_index(self, request, obj=None): # Internal method with "protected access" to handle translation differences. # This is only called when 'fluent_pages' is in the INSTALLED_APPS. from fluent_pages.urlresolvers import mixed_reverse return mixed_reverse('faqquestion_index')