class LinkFields(models.Model): link_external = models.URLField("External link", blank=True) link_page = models.ForeignKey('tuiuiucore.Page', null=True, blank=True, related_name='+', on_delete=models.CASCADE) link_document = models.ForeignKey('tuiuiudocs.Document', null=True, blank=True, related_name='+', on_delete=models.CASCADE) @property def link(self): if self.link_page: return self.link_page.url elif self.link_document: return self.link_document.url else: return self.link_external panels = [ FieldPanel('link_external'), PageChooserPanel('link_page'), DocumentChooserPanel('link_document'), ] class Meta: abstract = True
class Alternative(Orderable): experiment = ParentalKey(Experiment, related_name='alternatives', on_delete=models.CASCADE) page = models.ForeignKey('tuiuiucore.Page', related_name='+', on_delete=models.CASCADE) panels = [ PageChooserPanel('page'), ]
def test_autodetect_page_type(self): # Model has a foreign key to EventPage, which we want to autodetect # instead of specifying the page type in PageChooserPanel MyPageObjectList = ObjectList([PageChooserPanel('page') ]).bind_to_model(EventPageChooserModel) MyPageChooserPanel = MyPageObjectList.children[0] PageChooserForm = MyPageObjectList.get_form_class( EventPageChooserModel) form = PageChooserForm(instance=self.test_instance) page_chooser_panel = MyPageChooserPanel(instance=self.test_instance, form=form) result = page_chooser_panel.render_as_field() expected_js = 'createPageChooser("{id}", ["{model}"], {parent}, false, null);'.format( id="id_page", model="tests.eventpage", parent=self.events_index_page.id) self.assertIn(expected_js, result)
def test_override_page_type(self): # Model has a foreign key to Page, but we specify EventPage in the PageChooserPanel # to restrict the chooser to that page type MyPageObjectList = ObjectList([ PageChooserPanel('page', 'tests.EventPage') ]).bind_to_model(EventPageChooserModel) MyPageChooserPanel = MyPageObjectList.children[0] PageChooserForm = MyPageObjectList.get_form_class( EventPageChooserModel) form = PageChooserForm(instance=self.test_instance) page_chooser_panel = MyPageChooserPanel(instance=self.test_instance, form=form) result = page_chooser_panel.render_as_field() expected_js = 'createPageChooser("{id}", ["{model}"], {parent}, false, null);'.format( id="id_page", model="tests.eventpage", parent=self.events_index_page.id) self.assertIn(expected_js, result)
def setUp(self): model = PageChooserModel # a model with a foreign key to Page which we want to render as a page chooser # a PageChooserPanel class that works on PageChooserModel's 'page' field self.EditHandler = ObjectList([PageChooserPanel('page') ]).bind_to_model(PageChooserModel) self.MyPageChooserPanel = self.EditHandler.children[0] # build a form class containing the fields that MyPageChooserPanel wants self.PageChooserForm = self.EditHandler.get_form_class( PageChooserModel) # a test instance of PageChooserModel, pointing to the 'christmas' page self.christmas_page = Page.objects.get(slug='christmas') self.events_index_page = Page.objects.get(slug='events') self.test_instance = model.objects.create(page=self.christmas_page) self.form = self.PageChooserForm(instance=self.test_instance) self.page_chooser_panel = self.MyPageChooserPanel( instance=self.test_instance, form=self.form)
def test_render_js_init_with_can_choose_root_true(self): # construct an alternative page chooser panel object, with can_choose_root=True MyPageObjectList = ObjectList([ PageChooserPanel('page', can_choose_root=True) ]).bind_to_model(PageChooserModel) MyPageChooserPanel = MyPageObjectList.children[0] PageChooserForm = MyPageObjectList.get_form_class( EventPageChooserModel) form = PageChooserForm(instance=self.test_instance) page_chooser_panel = MyPageChooserPanel(instance=self.test_instance, form=form) result = page_chooser_panel.render_as_field() # the canChooseRoot flag on createPageChooser should now be true expected_js = 'createPageChooser("{id}", ["{model}"], {parent}, true, null);'.format( id="id_page", model="tuiuiucore.page", parent=self.events_index_page.id) self.assertIn(expected_js, result)
class Experiment(ClusterableModel): STATUS_CHOICES = [ ('draft', "Draft"), ('live', "Live"), ('completed', "Completed"), ] name = models.CharField(max_length=255) slug = models.SlugField(max_length=255) control_page = models.ForeignKey('tuiuiucore.Page', related_name='+', on_delete=models.CASCADE) goal = models.ForeignKey('tuiuiucore.Page', related_name='+', on_delete=models.SET_NULL, null=True, blank=True) status = models.CharField(max_length=10, choices=STATUS_CHOICES, default='draft') winning_variation = models.ForeignKey('tuiuiucore.Page', related_name='+', on_delete=models.SET_NULL, null=True) panels = [ FieldPanel('name'), FieldPanel('slug'), PageChooserPanel('control_page'), InlinePanel('alternatives', label="Alternatives"), PageChooserPanel('goal'), FieldPanel('status'), ] def __init__(self, *args, **kwargs): super(Experiment, self).__init__(*args, **kwargs) self._initial_status = self.status def activate_alternative_draft_content(self): # For any alternative pages that are unpublished, copy the latest draft revision # to the main table (with is_live=False) so that the revision shown as an alternative # is not an out-of-date one for alternative in self.alternatives.select_related('page'): if not alternative.page.live: revision = alternative.page.get_latest_revision_as_page() revision.live = False revision.has_unpublished_changes = True revision.save() def get_variations(self): return [self.control_page] + [ alt.page for alt in self.alternatives.select_related('page') ] def get_variation_for_user(self, user_id): variations = self.get_variations() # choose uniformly from variations, based on a hash of user_id and experiment.slug hash_input = "{0}.{1}".format(self.slug, user_id) hash_str = sha1(hash_input.encode('utf-8')).hexdigest()[:7] variation_index = int(hash_str, 16) % len(variations) return variations[variation_index] def start_experiment_for_user(self, user_id, request): """ Record a new participant and return the variation for them to use """ variation = self.get_variation_for_user(user_id) get_backend().record_participant(self, user_id, variation, request) return variation def record_completion_for_user(self, user_id, request): backend = get_backend() variation = self.get_variation_for_user(user_id) backend.record_completion(self, user_id, variation, request) def select_winner(self, variation): self.winning_variation = variation self.status = 'completed' self.save() def __str__(self): return self.name
def test_target_models_nonexistent_type(self): result = PageChooserPanel( 'barbecue', 'snowman.lorry').bind_to_model(PageChooserModel) self.assertRaises(ImproperlyConfigured, result.target_models)
def test_target_models(self): result = PageChooserPanel( 'barbecue', 'tuiuiucore.site').bind_to_model(PageChooserModel).target_models() self.assertEqual(result, [Site])