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)
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')
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
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')
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])
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)
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
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)