Ejemplo n.º 1
0
    def test_for_request_result_caching(self):
        # repeat test to show caching is unique per request instance,
        # even when the requests are for the same site
        for i, request in enumerate([self.get_request(), self.get_request()], 1):
            with self.subTest(attempt=i):

                # force site query beforehand
                Site.find_for_request(request)

                # only the first lookup should result in a query
                with self.assertNumQueries(1):
                    for i in range(4):
                        TestSiteSetting.for_request(request)
Ejemplo n.º 2
0
    def test_models_cached(self):
        """Accessing a setting should only hit the DB once per render"""
        get_title = '{{ settings("tests.testgenericsetting").title }}'

        request = self.get_request()
        # run extra query before hand
        Site.find_for_request(request)

        for i in range(1, 4):
            with self.assertNumQueries(1):
                context = {"request": request}
                template = self.engine.from_string(get_title * i)
                self.assertEqual(template.render(context),
                                 self.default_settings.title * i)
Ejemplo n.º 3
0
    def test_select_related(self, expected_queries=4):
        """The `select_related` attribute on setting models is `None` by default, so fetching foreign keys values requires additional queries"""
        request = self.get_request()

        self._create_importantpages_object()

        # force site query beforehand
        Site.find_for_request(request)

        # fetch settings and access foreiegn keys
        with self.assertNumQueries(expected_queries):
            settings = ImportantPages.for_request(request)
            settings.sign_up_page
            settings.general_terms_page
            settings.privacy_policy_page
Ejemplo n.º 4
0
def redirect_to_relevant_instance(request, app_name, model_name):
    model = get_model_from_url_params(app_name, model_name)

    if issubclass(model, BaseSiteSetting):
        # Redirect the user to the edit page for the current site
        # (or the current request does not correspond to a site, the first site in the list)
        site_request = Site.find_for_request(request)
        site = site_request or Site.objects.first()
        if not site:
            messages.error(
                request,
                _("This setting could not be opened because there is no site defined."),
            )
            return redirect("wagtailadmin_home")
        return redirect(
            "wagtailsettings:edit",
            app_name,
            model_name,
            site.pk,
        )
    elif issubclass(model, BaseGenericSetting):
        return redirect(
            "wagtailsettings:edit",
            app_name,
            model_name,
            model.load(request_or_site=request).id,
        )
    else:
        raise NotImplementedError
Ejemplo n.º 5
0
def pageurl(context, page, fallback=None):
    """
    Outputs a page's URL as relative (/foo/bar/) if it's within the same site as the
    current page, or absolute (http://example.com/foo/bar/) if not.
    If kwargs contains a fallback view name and page is None, the fallback view url will be returned.
    """
    if page is None and fallback:
        return resolve_url(fallback)

    if not hasattr(page, "relative_url"):
        raise ValueError("pageurl tag expected a Page object, got %r" % page)

    try:
        site = Site.find_for_request(context["request"])
        current_site = site
    except KeyError:
        # request not available in the current context; fall back on page.url
        return page.url

    if current_site is None:
        # request does not correspond to a recognised site; fall back on page.url
        return page.url

    # Pass page.relative_url the request object, which may contain a cached copy of
    # Site.get_site_root_paths()
    # This avoids page.relative_url having to make a database/cache fetch for this list
    # each time it's called.
    return page.relative_url(current_site, request=context.get("request"))
Ejemplo n.º 6
0
def slugurl(context, slug):
    """
    Returns the URL for the page that has the given slug.

    First tries to find a page on the current site. If that fails or a request
    is not available in the context, then returns the URL for the first page
    that matches the slug on any site.
    """

    page = None
    try:
        site = Site.find_for_request(context["request"])
        current_site = site
    except KeyError:
        # No site object found - allow the fallback below to take place.
        pass
    else:
        if current_site is not None:
            page = Page.objects.in_site(current_site).filter(slug=slug).first()

    # If no page is found, fall back to searching the whole tree.
    if page is None:
        page = Page.objects.filter(slug=slug).first()

    if page:
        # call pageurl() instead of page.relative_url() here so we get the ``accepts_kwarg`` logic
        return pageurl(context, page)
Ejemplo n.º 7
0
    def get_wagtail_site(self):
        from wagtail.models import Site

        site = Site.find_for_request(self.request)
        if site is None:
            return Site.objects.select_related("root_page").get(is_default_site=True)
        return site
Ejemplo n.º 8
0
    def test_models_cached(self):
        """Accessing a setting should only hit the DB once per request instance,
        even if using that request to rendering multiple times"""
        request = self.get_request()
        get_title = "{{ settings.tests.testgenericsetting.title }}"

        # force site query beforehand
        Site.find_for_request(request)

        with self.assertNumQueries(1):
            for i in range(1, 4):
                with self.subTest(attempt=i):
                    self.assertEqual(
                        self.render(request, get_title * i),
                        self.default_settings.title * i,
                    )
Ejemplo n.º 9
0
        def resolve_pages(self, info, **kwargs):
            pages = (WagtailPage.objects.live().public().filter(
                depth__gt=1).specific())  # no need to the root page

            if kwargs.get("in_site", False):
                site = Site.find_for_request(info.context)
                pages = pages.in_site(site)

            content_type = kwargs.pop("content_type", None)
            if content_type:
                app_label, model = content_type.strip().lower().split(".")
                try:
                    ctype = ContentType.objects.get(app_label=app_label,
                                                    model=model)
                except:  # noqa
                    return (WagtailPage.objects.none()
                            )  # something not quite right here, bail out early
                else:
                    pages = pages.filter(content_type=ctype)

            language_code = kwargs.pop("language_code", None)

            if language_code:
                pages = pages.filter(locale__language_code=language_code)

            return resolve_queryset(pages, info, **kwargs)
Ejemplo n.º 10
0
 def _inner(request):
     site = Site.find_for_request(request)
     if site is None:
         # find_for_request() can't determine the site,
         # so no settings can be idenfified
         return {}
     else:
         return SettingsProxy(request)
Ejemplo n.º 11
0
 def test_get_base_url_prefers_setting(self):
     request = RequestFactory().get("/")
     site = self.prepare_site()
     self.assertEqual(site, Site.find_for_request(request))
     self.assertEqual(get_base_url(request), "https://bar.example.com")
     with override_settings(WAGTAILAPI_BASE_URL=None):
         self.assertEqual(get_base_url(request),
                          "http://other.example.com:8080")
Ejemplo n.º 12
0
    def test_get_urls_with_request_site_cache_with_i18n(self):
        request, django_site = self.get_request_and_django_site("/sitemap.xml")
        req_protocol = request.scheme

        sitemap = Sitemap(request)

        # pre-seed find_for_request cache, so that it's not counted towards the query count
        Site.find_for_request(request)

        with self.assertNumQueries(16):
            urls = [
                url["location"]
                for url in sitemap.get_urls(1, django_site, req_protocol)
            ]

        self.assertIn("http://localhost/", urls)  # Homepage
        self.assertIn("http://localhost/hello-world/", urls)  # Child page
Ejemplo n.º 13
0
 def process_request(self, request):
     """
     Set request.site to contain the Site object responsible for handling this request,
     according to hostname matching rules
     """
     try:
         request.site = Site.find_for_request(request)
     except Site.DoesNotExist:
         request.site = None
Ejemplo n.º 14
0
def wagtail_site(context):
    """
    Returns the Site object for the given request
    """
    try:
        request = context["request"]
    except KeyError:
        return None

    return Site.find_for_request(request=request)
Ejemplo n.º 15
0
def get_base_url(request=None):
    site = Site.find_for_request(request)
    base_url = getattr(settings, 'WAGTAILAPI_BASE_URL',
                       site.root_url if request and site else None)

    if base_url:
        # We only want the scheme and netloc
        base_url_parsed = urlparse(base_url)

        return base_url_parsed.scheme + '://' + base_url_parsed.netloc
Ejemplo n.º 16
0
 def resolve_page(self, info, **kwargs):
     return preview_observable(
         id=kwargs.get("id"),
         slug=kwargs.get("slug"),
         url_path=kwargs.get("url_path"),
         token=kwargs.get("token"),
         content_type=kwargs.get("content_type"),
         site=Site.find_for_request(info.context) if kwargs.get(
             "in_site", False) else None,
     )
Ejemplo n.º 17
0
        def resolve_page(self, info, **kwargs):

            return get_specific_page(
                id=kwargs.get("id"),
                slug=kwargs.get("slug"),
                url_path=kwargs.get("url_path"),
                language_code=kwargs.get("language_code"),
                token=kwargs.get("token"),
                content_type=kwargs.get("content_type"),
                site=Site.find_for_request(info.context) if kwargs.get(
                    "in_site", False) else None,
            )
Ejemplo n.º 18
0
def _get_redirect(request, path):
    if ("\0" in path
        ):  # reject URLs with null characters, which crash on Postgres (#4496)
        return None

    site = Site.find_for_request(request)
    try:
        return models.Redirect.get_for_site(site).get(old_path=path)
    except models.Redirect.MultipleObjectsReturned:
        # We have a site-specific and a site-ambivalent redirect; prefer the specific one
        return models.Redirect.objects.get(site=site, old_path=path)
    except models.Redirect.DoesNotExist:
        return None
Ejemplo n.º 19
0
def edit_current_site(request, app_name, model_name):
    # Redirect the user to the edit page for the current site
    # (or the current request does not correspond to a site, the first site in the list)
    site_request = Site.find_for_request(request)
    site = site_request or Site.objects.first()
    if not site:
        messages.error(
            request,
            _("This setting could not be opened because there is no site defined."
              ),
        )
        return redirect("wagtailadmin_home")
    return redirect("wagtailsettings:edit", app_name, model_name, site.pk)
Ejemplo n.º 20
0
def get_base_url(request=None):
    base_url = getattr(settings, "WAGTAILAPI_BASE_URL", None)

    if base_url is None and request:
        site = Site.find_for_request(request)
        if site:
            base_url = site.root_url

    if base_url:
        # We only want the scheme and netloc
        base_url_parsed = urlparse(force_str(base_url))

        return base_url_parsed.scheme + "://" + base_url_parsed.netloc
Ejemplo n.º 21
0
 def for_request(cls, request):
     """
     Get or create an instance of this model for the request,
     and cache the result on the request for faster repeat access.
     """
     attr_name = cls.get_cache_attr_name()
     if hasattr(request, attr_name):
         return getattr(request, attr_name)
     site = Site.find_for_request(request)
     site_settings = cls.for_site(site)
     # to allow more efficient page url generation
     site_settings._request = request
     setattr(request, attr_name, site_settings)
     return site_settings
Ejemplo n.º 22
0
def get_setting(context, model_string, use_default_site=False):
    cache_key = None
    if use_default_site:
        cache_key = Site.objects.get(is_default_site=True)
    elif "request" in context:
        cache_key = Site.find_for_request(context["request"])

    # Sadly, WeakKeyDictionary can not implement __missing__, so we have to do
    # this one manually
    try:
        context_cache = settings_cache[context]
    except KeyError:
        context_cache = settings_cache[context] = SettingContextCache()
    # These ones all implement __missing__ in a useful way though
    return context_cache[cache_key][model_string]
Ejemplo n.º 23
0
    def find_object(self, queryset, request):
        site = Site.find_for_request(request)
        if 'html_path' in request.GET and site is not None:
            path = request.GET['html_path']
            path_components = [component for component in path.split('/') if component]

            try:
                page, _, _ = site.root_page.specific.route(request, path_components)
            except Http404:
                return

            if queryset.filter(id=page.id).exists():
                return page

        return super().find_object(queryset, request)
Ejemplo n.º 24
0
    def test_get_base_url_from_request(self):
        # base url for siteless request should be None
        request = RequestFactory().get("/")
        self.assertIsNone(Site.find_for_request(request))
        self.assertIsNone(get_base_url(request))

        # base url for request with a site should be based on the site's details
        site = self.prepare_site()
        self.clear_cached_site(request)
        self.assertEqual(site, Site.find_for_request(request))
        self.assertEqual(get_base_url(request),
                         "http://other.example.com:8080")

        # port 443 should indicate https without a port
        site.port = 443
        site.save()
        self.clear_cached_site(request)
        self.assertEqual(get_base_url(request), "https://other.example.com")

        # port 80 should indicate http without a port
        site.port = 80
        site.save()
        self.clear_cached_site(request)
        self.assertEqual(get_base_url(request), "http://other.example.com")
Ejemplo n.º 25
0
def serve(request, path):
    # we need a valid Site object corresponding to this request in order to proceed
    site = Site.find_for_request(request)
    if not site:
        raise Http404

    path_components = [component for component in path.split("/") if component]
    page, args, kwargs = site.root_page.localized.specific.route(
        request, path_components
    )

    for fn in hooks.get_hooks("before_serve_page"):
        result = fn(page, request, args, kwargs)
        if isinstance(result, HttpResponse):
            return result

    return page.serve(request, *args, **kwargs)
Ejemplo n.º 26
0
def get_setting(context, model_string, use_default_site=False):
    if use_default_site:
        site = Site.objects.get(is_default_site=True)
    elif "request" in context:
        site = Site.find_for_request(context["request"])
    else:
        raise RuntimeError("No request found in context, and use_default_site "
                           "flag not set")

    # Sadly, WeakKeyDictionary can not implement __missing__, so we have to do
    # this one manually
    try:
        context_cache = settings_cache[context]
    except KeyError:
        context_cache = settings_cache[context] = ContextCache()
    # These ones all implement __missing__ in a useful way though
    return context_cache[site][model_string]
Ejemplo n.º 27
0
    def get_base_queryset(self):
        """
        Returns a queryset containing all pages that can be seen by this user.

        This is used as the base for get_queryset and is also used to find the
        parent pages when using the child_of and descendant_of filters as well.
        """
        # Get live pages that are not in a private section
        queryset = Page.objects.all().public().live()
        site = Site.find_for_request(self.request)

        # Filter by site
        if site:
            queryset = queryset.descendant_of(site.root_page, inclusive=True)
        else:
            # No sites configured
            queryset = queryset.none()

        return queryset
Ejemplo n.º 28
0
def routablepageurl(context, page, url_name, *args, **kwargs):
    """
    ``routablepageurl`` is similar to ``pageurl``, but works with
    pages using ``RoutablePageMixin``. It behaves like a hybrid between the built-in
    ``reverse``, and ``pageurl`` from Wagtail.

    ``page`` is the RoutablePage that URLs will be generated from.

    ``url_name`` is a URL name defined in ``page.subpage_urls``.

    Positional arguments and keyword arguments should be passed as normal
    positional arguments and keyword arguments.
    """
    request = context["request"]
    site = Site.find_for_request(request)
    base_url = page.relative_url(site, request)
    routed_url = page.reverse_subpage(url_name, args=args, kwargs=kwargs)
    if not base_url.endswith("/"):
        base_url += "/"
    return base_url + routed_url
Ejemplo n.º 29
0
def meta_tags(request, model):
    if not request:
        raise TemplateSyntaxError("'meta_tags' missing request from context")
    if not model:
        raise TemplateSyntaxError(
            "'meta_tags' tag is missing a model or object")
    context = {
        'site_name': Site.find_for_request(request).site_name,
        'twitter_card_type': model.get_twitter_card_type(request),
        'object': model,
    }

    meta_image = model.get_meta_image_url(request)
    if meta_image:
        width, height = model.get_meta_image_dimensions()
        context['meta_image_width'] = width
        context['meta_image_height'] = height
    context['meta_image'] = meta_image

    return render_to_string('wagtailmetadata/parts/tags.html',
                            context,
                            request=request)
Ejemplo n.º 30
0
    def test_pages_in_site(self):
        query = """
        {
            pages(inSite: true) {
                title
                contentType
                pageType
            }
        }
        """

        request = self.factory.get("/")
        executed = self.client.execute(query, context_value=request)

        self.assertEquals(type(executed["data"]), dict_type)
        self.assertEquals(type(executed["data"]["pages"]), list)
        self.assertEquals(type(executed["data"]["pages"][0]), dict_type)

        site = Site.find_for_request(request)
        pages = Page.objects.in_site(site)

        self.assertEquals(len(executed["data"]["pages"]), pages.count())