def render(self, value, context=None):
        """Only render this content block for users in this segment.

        :param value: The value from the block
        :type value: dict
        :param context: The context containing the request
        :type context: dict
        :returns: The provided block if matched, otherwise an empty string
        :rtype: blocks.StructBlock or empty str

        """
        if context is None or 'request' not in context:
            return super(PersonalisedStructBlock, self).render(value, context)

        request = context['request']
        adapter = get_segment_adapter(request)
        user_segments = adapter.get_segments()

        try:
            segment_id = int(value['segment'])
        except (ValueError, TypeError):
            return ''

        if segment_id > 0:
            for segment in user_segments:
                if segment.id == segment_id:
                    return super(PersonalisedStructBlock,
                                 self).render(value, context)

        if segment_id == -1:
            return super(PersonalisedStructBlock, self).render(value, context)

        return ''
def serve_variation(page, request, serve_args, serve_kwargs):
    """Apply a segment to a visitor before serving the page.

    :param page: The page being served
    :type page: wagtail.wagtailcore.models.Page
    :param request: The http request
    :type request: django.http.HttpRequest
    :returns: A variation if one is available for the visitor's segment,
              otherwise the original page
    :rtype: wagtail.wagtailcore.models.Page

    """
    user_segments = []
    if not isinstance(page, PersonalisablePageMixin):
        return

    adapter = get_segment_adapter(request)
    user_segments = adapter.get_segments()

    if user_segments:
        variations = page.variants_for_segments(user_segments)
        if variations:
            variation = variations.first()
            impersonate_other_page(variation, page)
            return variation.serve(request, *serve_args, **serve_kwargs)
    def test_user(self, request, user=None):
        if user:
            # Create a fake request so we can use the adapter
            request = RequestFactory().get('/')
            request.session = SessionStore()
            request.user = user
        elif not request:
            # Return false if we don't have a user or a request
            return False

        # Django formsets don't honour 'required' fields so check rule is valid
        try:
            self.tag
        except ObjectDoesNotExist:
            return False

        from wagtail_personalisation.adapters import get_segment_adapter
        operator = self.OPERATORS[self.operator]
        adapter = get_segment_adapter(request)
        visit_count = adapter.get_tag_count(
            self.tag,
            self.date_from,
            self.date_to,
        )

        return operator(visit_count, self.count)
def serve_variant(page, request, serve_args, serve_kwargs):
    """Apply a segment to a visitor before serving the page.

    :param page: The page being served
    :type page: wagtail.core.models.Page
    :param request: The http request
    :type request: django.http.HttpRequest
    :returns: A variant if one is available for the visitor's segment,
              otherwise the original page
    :rtype: wagtail.core.models.Page

    """
    user_segments = []
    if not isinstance(page, models.PersonalisablePageMixin):
        return

    adapter = get_segment_adapter(request)
    user_segments = adapter.get_segments()

    metadata = page.personalisation_metadata

    # If page is not canonical, don't serve it.
    if not metadata.is_canonical:
        raise Http404

    if user_segments:
        # TODO: This is never more then one page? (fix query count)
        metadata = metadata.metadata_for_segments(user_segments)
        if metadata:
            variant = metadata.first().variant.specific
            return variant.serve(request, *serve_args, **serve_kwargs)
Exemple #5
0
def segment_user(page, request, serve_args, serve_kwargs):
    """Apply a segment to a visitor before serving the page.

    :param page: The page being served
    :type page: wagtail.core.models.Page
    :param request: The http request
    :type request: django.http.HttpRequest

    """
    adapter = get_segment_adapter(request)
    adapter.refresh()
def set_visit_count(page, request, serve_args, serve_kwargs):
    """Tests the provided rules to see if the request still belongs
    to a segment.

    :param page: The page being served
    :type page: wagtail.core.models.Page
    :param request: The http request
    :type request: django.http.HttpRequest

    """
    adapter = get_segment_adapter(request)
    adapter.add_page_visit(page)
def filter_forms_by_segments(forms, request):
    """Filter out forms not in user's segments."""
    user_segments = get_segment_adapter(request).get_segments()
    user_segments_ids = [s.id for s in user_segments]
    filtered_forms = []

    for form in forms:
        if not hasattr(form['molo_form_page'], 'segment_id') or \
                not form['molo_form_page'].segment_id \
                or form['molo_form_page'].segment_id in user_segments_ids:
            filtered_forms.append(form)

    return filtered_forms
def test_serve_variant_with_variant_segmented(site, rf, segmented_page):
    request = rf.get('/')
    args = tuple()
    kwargs = {}

    page = segmented_page.personalisation_metadata.canonical_page
    segment = segmented_page.personalisation_metadata.segment

    adapter = adapters.get_segment_adapter(request)
    adapter.set_segments([segment])

    result = wagtail_hooks.serve_variant(page, request, args, kwargs)
    assert result.status_code == 200
def filter_surveys_by_segments(surveys, request):
    """Filter out surveys not in user's segments."""
    user_segments = get_segment_adapter(request).get_segments()
    user_segments_ids = [s.id for s in user_segments]
    filtered_surveys = []

    for survey in surveys:
        if not hasattr(survey['molo_survey_page'], 'segment_id') or \
                not survey['molo_survey_page'].segment_id \
                or survey['molo_survey_page'].segment_id in user_segments_ids:
            filtered_surveys.append(survey)

    return filtered_surveys
    def get_user_info_string(self, user):
        # Create a fake request so we can use the adapter
        request = RequestFactory().get('/')
        request.session = SessionStore()
        request.user = user

        from wagtail_personalisation.adapters import get_segment_adapter
        adapter = get_segment_adapter(request)
        visit_count = adapter.get_tag_count(
            self.tag,
            self.date_from,
            self.date_to,
        )
        return str(visit_count)
    def serve(self, request, *args, **kwargs):
        # We need request data in self.get_form_fields() to perform
        # segmentation.
        # TODO(tmkn): This is quite hacky, need to come up with better solution
        self.request = request

        # Check whether it is segmented and raise 404 if segments do not match
        if not getattr(request, 'is_preview', False):
            if (self.segment_id
                    and get_segment_adapter(request).get_segment_by_id(
                        self.segment_id) is None):
                raise Http404("Form does not match your segments.")

        return super(PersonalisableForm, self).serve(request, *args, **kwargs)
    def get_form_fields(self):
        """Get form fields for particular segments."""
        # Get only segmented form fields if serve() has been called
        # (because the page is being seen by user on the front-end)
        if self.is_front_end_request():
            user_segments_ids = [
                s.id for s in get_segment_adapter(self.request).get_segments()
            ]

            return self.personalisable_form_fields.filter(
                Q(segment=None) | Q(segment_id__in=user_segments_ids))

        # Return all form fields if there's no request passed
        # (used on the admin site so serve() will not be called).
        return self.personalisable_form_fields.select_related('segment')
Exemple #13
0
    def serve(self, request, *args, **kwargs):
        # We need request data in self.get_form_fields() to perform
        # segmentation.
        # TODO(tmkn): This is quite hacky, need to come up with better solution
        self.request = request

        # Check whether it is segmented and raise 404 if segments do not match
        if not getattr(request, 'is_preview', False):
            if (self.segment_id and
                get_segment_adapter(request).get_segment_by_id(
                    self.segment_id) is None):
                raise Http404("Survey does not match your segments.")

        return super(PersonalisableSurvey, self).serve(
            request, *args, **kwargs)
    def render(self, context):
        # Check if segment exists
        name = self.name.resolve(context)
        segment = Segment.objects.enabled().filter(name=name).first()
        if not segment:
            return ""

        # Check if user has segment
        adapter = get_segment_adapter(context['request'])
        user_segment = adapter.get_segment_by_id(segment_id=segment.pk)
        if not user_segment:
            return ''

        content = self.nodelist.render(context)
        content = mark_safe(content)
        return content
Exemple #15
0
    def get_form_fields(self):
        """Get form fields for particular segments."""
        # Get only segmented form fields if serve() has been called
        # (because the page is being seen by user on the front-end)
        if self.is_front_end_request():
            user_segments_ids = [
                s.id for s in get_segment_adapter(self.request).get_segments()
            ]

            return self.personalisable_survey_form_fields.filter(
                Q(segment=None) | Q(segment_id__in=user_segments_ids)
            )

        # Return all form fields if there's no request passed
        # (used on the admin site so serve() will not be called).
        return self.personalisable_survey_form_fields.select_related('segment')
Exemple #16
0
    def process_template_response(self, request, response):
        try:
            adapter = get_segment_adapter(request)
            user_segments = adapter.get_segments()

            if user_segments:
                page = response.context_data['page']
                metadata = page.personalisation_metadata
                metadata = metadata.metadata_for_segments(user_segments)
                if metadata:
                    chosen_segment = metadata.first().segment
                    response.context_data.update(
                        {'chosen_segment': chosen_segment})
        except Exception as e:
            pass

        return response
def segment_user(page, request, serve_args, serve_kwargs):
    """Apply a segment to a visitor before serving the page.

    :param page: The page being served
    :type page: wagtail.core.models.Page
    :param request: The http request
    :type request: django.http.HttpRequest

    """
    adapter = get_segment_adapter(request)
    adapter.refresh()

    forced_segment = request.GET.get('segment', None)
    if request.user.is_superuser and forced_segment is not None:
        segment = models.Segment.objects.filter(pk=forced_segment).first()
        if segment:
            adapter.set_segments([segment])
Exemple #18
0
    def get_user_info_string(self, user):
        # Local import for cyclic import
        from wagtail_personalisation.adapters import (
            get_segment_adapter, SessionSegmentsAdapter, SEGMENT_ADAPTER_CLASS)

        # Create a fake request so we can use the adapter
        request = RequestFactory().get('/')
        request.user = user

        # If we're using the session adapter check for an active session
        if SEGMENT_ADAPTER_CLASS == SessionSegmentsAdapter:
            request.session = self._get_user_session(user)
        else:
            request.session = SessionStore()

        adapter = get_segment_adapter(request)
        visit_count = adapter.get_visit_count(self.counted_page)
        return str(visit_count)
Exemple #19
0
    def test_user(self, request, user=None):
        # Local import for cyclic import
        from wagtail_personalisation.adapters import (get_segment_adapter,
                                                      SessionSegmentsAdapter,
                                                      SEGMENT_ADAPTER_CLASS)

        # Django formsets don't honour 'required' fields so check rule is valid
        try:
            self.counted_page
        except ObjectDoesNotExist:
            return False

        if user:
            # Create a fake request so we can use the adapter
            request = RequestFactory().get('/')
            request.user = user

            # If we're using the session adapter check for an active session
            if SEGMENT_ADAPTER_CLASS == SessionSegmentsAdapter:
                request.session = self._get_user_session(user)
            else:
                request.session = SessionStore()

        elif not request:
            # Return false if we don't have a user or a request
            return False

        operator = self.operator
        segment_count = self.count

        adapter = get_segment_adapter(request)

        visit_count = adapter.get_visit_count(self.counted_page)
        if visit_count and operator == "more_than":
            if visit_count > segment_count:
                return True
        elif visit_count and operator == "less_than":
            if visit_count < segment_count:
                return True
        elif visit_count and operator == "equal_to":
            if visit_count == segment_count:
                return True
        return False
Exemple #20
0
    def test_user(self, request):
        operator = self.operator
        segment_count = self.count

        # Local import for cyclic import
        from wagtail_personalisation.adapters import get_segment_adapter

        adapter = get_segment_adapter(request)

        visit_count = adapter.get_visit_count(self.counted_page)
        if visit_count and operator == "more_than":
            if visit_count > segment_count:
                return True
        elif visit_count and operator == "less_than":
            if visit_count < segment_count:
                return True
        elif visit_count and operator == "equal_to":
            if visit_count == segment_count:
                return True
        return False
    def render(self, value, context=None):
        """Only render this content block for users in this segment.

        :param value: The value from the block
        :type value: dict
        :param context: The context containing the request
        :type context: dict
        :returns: The provided block if matched, otherwise an empty string
        :rtype: blocks.StructBlock or empty str

        """
        request = context['request']
        adapter = get_segment_adapter(request)
        user_segments = adapter.get_segments()

        if value['segment']:
            for segment in user_segments:
                if segment.id == int(value['segment']):
                    return super(PersonalisedStructBlock,
                                 self).render(value, context)

        return ""
    def setUp(self):
        # Fabricate a request with a logged-in user
        # so we can use it to test the segment rule
        self.mk_main()
        self.request_factory = RequestFactory()
        self.request = self.request_factory.get('/')
        self.request.user = get_user_model().objects.create_user(
            username='******', email='*****@*****.**', password='******')
        middleware = SessionMiddleware()
        middleware.process_request(self.request)
        self.request.session.save()

        self.section = SectionPage(title='test section')
        self.section_index.add_child(instance=self.section)

        self.tag = Tag(title='test')
        self.tag_index.add_child(instance=self.tag)
        self.tag.save_revision()

        self.article = self.add_article(title='test article', tags=[self.tag])

        self.adapter = get_segment_adapter(self.request)