示例#1
0
class CustomRichTextFieldPage(Page):
    body = RichTextField(editor='custom')

    content_panels = [
        FieldPanel('title', classname="full title"),
        FieldPanel('body'),
    ]
示例#2
0
class AbstractCarouselItem(AbstractLinkFields):
    image = models.ForeignKey(
        'tuiuiuimages.Image',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+'
    )
    embed_url = models.URLField("Embed URL", blank=True)
    caption = models.CharField(max_length=255, blank=True)

    api_fields = (
        'image',
        'embed_url',
        'caption',
    ) + AbstractLinkFields.api_fields

    panels = [
        ImageChooserPanel('image'),
        FieldPanel('embed_url'),
        FieldPanel('caption'),
        MultiFieldPanel(AbstractLinkFields.panels, "Link"),
    ]

    class Meta:
        abstract = True
示例#3
0
class SimplePage(Page):
    content = models.TextField()

    content_panels = [
        FieldPanel('title', classname="full title"),
        FieldPanel('content'),
    ]
示例#4
0
class DefaultRichTextFieldPage(Page):
    body = RichTextField()

    content_panels = [
        FieldPanel('title', classname="full title"),
        FieldPanel('body'),
    ]
    def setUp(self):
        self.EventPageForm = get_form_for_model(EventPage,
                                                form_class=TuiuiuAdminPageForm,
                                                formsets=[])
        self.event = EventPage(title='Abergavenny sheepdog trials',
                               date_from=date(2014, 7, 20),
                               date_to=date(2014, 7, 21))

        self.EndDatePanel = FieldPanel(
            'date_to', classname='full-width').bind_to_model(EventPage)
 def setUp(self):
     # a custom ObjectList for EventPage
     self.EventPageObjectList = ObjectList(
         [
             FieldPanel('title', widget=forms.Textarea),
             FieldPanel('date_from'),
             FieldPanel('date_to'),
             InlinePanel('speakers', label="Speakers"),
         ],
         heading='Event details',
         classname="shiny").bind_to_model(EventPage)
    def setUp(self):
        self.EventPageForm = get_form_for_model(EventPage,
                                                form_class=TuiuiuAdminPageForm,
                                                formsets=[])
        self.event = EventPage(title='Abergavenny sheepdog trials',
                               date_from=date(2014, 7, 20),
                               date_to=date(2014, 7, 21))

        self.DatesPanel = FieldRowPanel([
            FieldPanel('date_from', classname='col4'),
            FieldPanel('date_to', classname='coltwo'),
        ]).bind_to_model(EventPage)
示例#8
0
class Advert(ClusterableModel):
    url = models.URLField(null=True, blank=True)
    text = models.CharField(max_length=255)

    tags = TaggableManager(through=AdvertTag, blank=True)

    panels = [
        FieldPanel('url'),
        FieldPanel('text'),
        FieldPanel('tags'),
    ]

    def __str__(self):
        return self.text
 def setUp(self):
     # a custom tabbed interface for EventPage
     self.EventPageTabbedInterface = TabbedInterface([
         ObjectList([
             FieldPanel('title', widget=forms.Textarea),
             FieldPanel('date_from'),
             FieldPanel('date_to'),
         ],
                    heading='Event details',
                    classname="shiny"),
         ObjectList([
             InlinePanel('speakers', label="Speakers"),
         ],
                    heading='Speakers'),
     ]).bind_to_model(EventPage)
示例#10
0
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
示例#11
0
class SectionedRichTextPageSection(Orderable):
    page = ParentalKey('tests.SectionedRichTextPage',
                       related_name='sections',
                       on_delete=models.CASCADE)
    body = RichTextField()

    panels = [FieldPanel('body')]
示例#12
0
class ValidatedPage(Page):
    foo = models.CharField(max_length=255)

    base_form_class = ValidatedPageForm
    content_panels = Page.content_panels + [
        FieldPanel('foo'),
    ]
示例#13
0
class ContactFieldsMixin(models.Model):
    telephone = models.CharField(max_length=20, blank=True)
    email = models.EmailField(blank=True)
    address_1 = models.CharField(max_length=255, blank=True)
    address_2 = models.CharField(max_length=255, blank=True)
    city = models.CharField(max_length=255, blank=True)
    country = models.CharField(max_length=255, blank=True)
    post_code = models.CharField(max_length=10, blank=True)

    api_fields = (
        'telephone',
        'email',
        'address_1',
        'address_2',
        'city',
        'country',
        'post_code',
    )

    panels = [
        FieldPanel('telephone'),
        FieldPanel('email'),
        FieldPanel('address_1'),
        FieldPanel('address_2'),
        FieldPanel('city'),
        FieldPanel('country'),
        FieldPanel('post_code'),
    ]

    class Meta:
        abstract = True
示例#14
0
class CustomRichBlockFieldPage(Page):
    body = StreamField([
        ('rich_text', RichTextBlock(editor='custom')),
    ])

    content_panels = [
        FieldPanel('title', classname="full title"),
        StreamFieldPanel('body'),
    ]
示例#15
0
class RichTextSection(models.Model):
    snippet = ParentalKey('MultiSectionRichTextSnippet',
                          related_name='sections',
                          on_delete=models.CASCADE)
    body = RichTextField()

    panels = [
        FieldPanel('body'),
    ]
示例#16
0
class RelatedLink(LinkFields):
    title = models.CharField(max_length=255, help_text="Link title")

    panels = [
        FieldPanel('title'),
        MultiFieldPanel(LinkFields.panels, "Link"),
    ]

    class Meta:
        abstract = True
示例#17
0
class BlogCategoryBlogPage(models.Model):
    category = models.ForeignKey(BlogCategory,
                                 related_name="+",
                                 on_delete=models.CASCADE)
    page = ParentalKey('ManyToManyBlogPage',
                       related_name='categories',
                       on_delete=models.CASCADE)
    panels = [
        FieldPanel('category'),
    ]
示例#18
0
class DefaultStreamPage(Page):
    body = StreamField([
        ('text', CharBlock()),
        ('rich_text', RichTextBlock()),
        ('image', ImageChooserBlock()),
    ],
                       default='')

    content_panels = [
        FieldPanel('title'),
        StreamFieldPanel('body'),
    ]
示例#19
0
class AbstractRelatedLink(AbstractLinkFields):
    title = models.CharField(max_length=255, help_text="Link title")

    api_fields = ('title', ) + AbstractLinkFields.api_fields

    panels = [
        FieldPanel('title'),
        MultiFieldPanel(AbstractLinkFields.panels, "Link"),
    ]

    class Meta:
        abstract = True
示例#20
0
class StreamPage(Page):
    body = StreamField([
        ('text', CharBlock()),
        ('rich_text', RichTextBlock()),
        ('image', ExtendedImageChooserBlock()),
    ])

    api_fields = ('body', )

    content_panels = [
        FieldPanel('title'),
        StreamFieldPanel('body'),
    ]
示例#21
0
class EventPageSpeaker(Orderable, LinkFields):
    page = ParentalKey('tests.EventPage',
                       related_name='speakers',
                       on_delete=models.CASCADE)
    first_name = models.CharField("Name", max_length=255, blank=True)
    last_name = models.CharField("Surname", max_length=255, blank=True)
    image = models.ForeignKey('tuiuiuimages.Image',
                              null=True,
                              blank=True,
                              on_delete=models.SET_NULL,
                              related_name='+')

    @property
    def name_display(self):
        return self.first_name + " " + self.last_name

    panels = [
        FieldPanel('first_name'),
        FieldPanel('last_name'),
        ImageChooserPanel('image'),
        MultiFieldPanel(LinkFields.panels, "Link"),
    ]
示例#22
0
class EventPageSpeaker(Orderable, AbstractLinkFields):
    page = ParentalKey('EventPage', related_name='speakers', on_delete=models.CASCADE)
    first_name = models.CharField("Name", max_length=255, blank=True)
    last_name = models.CharField("Surname", max_length=255, blank=True)
    image = models.ForeignKey(
        'tuiuiuimages.Image',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+'
    )

    api_fields = (
        'first_name',
        'last_name',
        'image',
    )

    panels = [
        FieldPanel('first_name'),
        FieldPanel('last_name'),
        ImageChooserPanel('image'),
        MultiFieldPanel(AbstractLinkFields.panels, "Link"),
    ]
示例#23
0
class AdvertWithTabbedInterface(models.Model):
    url = models.URLField(null=True, blank=True)
    text = models.CharField(max_length=255)
    something_else = models.CharField(max_length=255)

    advert_panels = [
        FieldPanel('url'),
        FieldPanel('text'),
    ]

    other_panels = [
        FieldPanel('something_else'),
    ]

    edit_handler = TabbedInterface([
        ObjectList(advert_panels, heading='Advert'),
        ObjectList(other_panels, heading='Other'),
    ])

    def __str__(self):
        return self.text

    class Meta:
        ordering = ('text', )
示例#24
0
class ManyToManyBlogPage(Page):
    """
    A page type with two different kinds of M2M relation.
    We don't formally support these, but we don't want them to cause
    hard breakages either.
    """
    body = RichTextField(blank=True)
    adverts = models.ManyToManyField(Advert, blank=True)
    blog_categories = models.ManyToManyField(BlogCategory,
                                             through=BlogCategoryBlogPage,
                                             blank=True)

    # make first_published_at editable on this page model
    settings_panels = Page.settings_panels + [
        FieldPanel('first_published_at'),
    ]
示例#25
0
class AbstractFormField(Orderable):
    """
    Database Fields required for building a Django Form field.
    """

    label = models.CharField(verbose_name=_('label'),
                             max_length=255,
                             help_text=_('The label of the form field'))
    field_type = models.CharField(verbose_name=_('field type'),
                                  max_length=16,
                                  choices=FORM_FIELD_CHOICES)
    required = models.BooleanField(verbose_name=_('required'), default=True)
    choices = models.TextField(
        verbose_name=_('choices'),
        blank=True,
        help_text=
        _('Comma separated list of choices. Only applicable in checkboxes, radio and dropdown.'
          ))
    default_value = models.CharField(
        verbose_name=_('default value'),
        max_length=255,
        blank=True,
        help_text=_(
            'Default value. Comma separated values supported for checkboxes.'))
    help_text = models.CharField(verbose_name=_('help text'),
                                 max_length=255,
                                 blank=True)

    @property
    def clean_name(self):
        # unidecode will return an ascii string while slugify wants a
        # unicode string on the other hand, slugify returns a safe-string
        # which will be converted to a normal str
        return str(slugify(text_type(unidecode(self.label))))

    panels = [
        FieldPanel('label'),
        FieldPanel('help_text'),
        FieldPanel('required'),
        FieldPanel('field_type', classname="formbuilder-type"),
        FieldPanel('choices', classname="formbuilder-choices"),
        FieldPanel('default_value', classname="formbuilder-default"),
    ]

    class Meta:
        abstract = True
        ordering = ['sort_order']
示例#26
0
    def test_no_thousand_separators_in_js(self):
        """
        Test that the USE_THOUSAND_SEPARATOR setting does not screw up the rendering of numbers
        (specifically maxForms=1000) in the JS initializer:
        https://github.com/tuiuiu/tuiuiu/pull/2699
        https://github.com/tuiuiu/tuiuiu/issues/3227
        """
        SpeakerObjectList = ObjectList([
            InlinePanel('speakers',
                        label="Speakers",
                        panels=[
                            FieldPanel('first_name', widget=forms.Textarea),
                            ImageChooserPanel('image'),
                        ]),
        ]).bind_to_model(EventPage)
        SpeakerInlinePanel = SpeakerObjectList.children[0]
        EventPageForm = SpeakerObjectList.get_form_class(EventPage)
        event_page = EventPage.objects.get(slug='christmas')
        form = EventPageForm(instance=event_page)
        panel = SpeakerInlinePanel(instance=event_page, form=form)

        self.assertIn('maxForms: 1000', panel.render_js_init())
示例#27
0
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
示例#28
0
    def test_render_with_panel_overrides(self):
        """
        Check that inline panel renders the panels listed in the InlinePanel definition
        where one is specified
        """
        SpeakerObjectList = ObjectList([
            InlinePanel('speakers',
                        label="Speakers",
                        panels=[
                            FieldPanel('first_name', widget=forms.Textarea),
                            ImageChooserPanel('image'),
                        ]),
        ]).bind_to_model(EventPage)
        SpeakerInlinePanel = SpeakerObjectList.children[0]
        EventPageForm = SpeakerObjectList.get_form_class(EventPage)

        # SpeakerInlinePanel should instruct the form class to include a 'speakers' formset
        self.assertEqual(['speakers'], list(EventPageForm.formsets.keys()))

        event_page = EventPage.objects.get(slug='christmas')

        form = EventPageForm(instance=event_page)
        panel = SpeakerInlinePanel(instance=event_page, form=form)

        result = panel.render_as_field()

        # rendered panel should contain first_name rendered as a text area, but no last_name field
        self.assertIn('<label for="id_speakers-0-first_name">Name:</label>',
                      result)
        self.assertIn('Father</textarea>', result)
        self.assertNotIn(
            '<label for="id_speakers-0-last_name">Surname:</label>', result)

        # test for #338: surname field should not be rendered as a 'stray' label-less field
        self.assertTagInHTML('<input id="id_speakers-0-last_name">',
                             result,
                             count=0,
                             allow_extra_attrs=True)

        self.assertIn('<label for="id_speakers-0-image">Image:</label>',
                      result)
        self.assertIn('Choose an image', result)

        # rendered panel must also contain hidden fields for id, DELETE and ORDER
        self.assertTagInHTML(
            '<input id="id_speakers-0-id" name="speakers-0-id" type="hidden">',
            result,
            allow_extra_attrs=True)
        self.assertTagInHTML(
            '<input id="id_speakers-0-DELETE" name="speakers-0-DELETE" type="hidden">',
            result,
            allow_extra_attrs=True)
        self.assertTagInHTML(
            '<input id="id_speakers-0-ORDER" name="speakers-0-ORDER" type="hidden">',
            result,
            allow_extra_attrs=True)

        # rendered panel must contain maintenance form for the formset
        self.assertTagInHTML(
            '<input id="id_speakers-TOTAL_FORMS" name="speakers-TOTAL_FORMS" type="hidden">',
            result,
            allow_extra_attrs=True)

        # render_js_init must provide the JS initializer
        self.assertIn('var panel = InlinePanel({', panel.render_js_init())
示例#29
0
class TestFieldPanel(TestCase):
    def setUp(self):
        self.EventPageForm = get_form_for_model(EventPage,
                                                form_class=TuiuiuAdminPageForm,
                                                formsets=[])
        self.event = EventPage(title='Abergavenny sheepdog trials',
                               date_from=date(2014, 7, 20),
                               date_to=date(2014, 7, 21))

        self.EndDatePanel = FieldPanel(
            'date_to', classname='full-width').bind_to_model(EventPage)

    def test_render_as_object(self):
        form = self.EventPageForm(
            {
                'title': 'Pontypridd sheepdog trials',
                'date_from': '2014-07-20',
                'date_to': '2014-07-22'
            },
            instance=self.event)

        form.is_valid()

        field_panel = self.EndDatePanel(instance=self.event, form=form)
        result = field_panel.render_as_object()

        # check that label appears as a legend in the 'object' wrapper,
        # but not as a field label (that would be provided by ObjectList instead)
        self.assertIn('<legend>End date</legend>', result)
        self.assertNotIn('<label for="id_date_to">End date:</label>', result)

        # check that help text is not included (it's provided by ObjectList instead)
        self.assertNotIn('Not required if event is on a single day', result)

        # check that the populated form field is included
        self.assertIn('value="2014-07-22"', result)

        # there should be no errors on this field
        self.assertNotIn('<p class="error-message">', result)

    def test_render_as_field(self):
        form = self.EventPageForm(
            {
                'title': 'Pontypridd sheepdog trials',
                'date_from': '2014-07-20',
                'date_to': '2014-07-22'
            },
            instance=self.event)

        form.is_valid()

        field_panel = self.EndDatePanel(instance=self.event, form=form)
        result = field_panel.render_as_field()

        # check that label is output in the 'field' style
        self.assertIn('<label for="id_date_to">End date:</label>', result)
        self.assertNotIn('<legend>End date</legend>', result)

        # check that help text is included
        self.assertIn('Not required if event is on a single day', result)

        # check that the populated form field is included
        self.assertIn('value="2014-07-22"', result)

        # there should be no errors on this field
        self.assertNotIn('<p class="error-message">', result)

    def test_required_fields(self):
        result = self.EndDatePanel.required_fields()
        self.assertEqual(result, ['date_to'])

    def test_error_message_is_rendered(self):
        form = self.EventPageForm(
            {
                'title': 'Pontypridd sheepdog trials',
                'date_from': '2014-07-20',
                'date_to': '2014-07-33'
            },
            instance=self.event)

        form.is_valid()

        field_panel = self.EndDatePanel(instance=self.event, form=form)
        result = field_panel.render_as_field()

        self.assertIn('<p class="error-message">', result)
        self.assertIn('<span>Enter a valid date.</span>', result)
示例#30
0
class PanelSettings(TestSetting):
    panels = [FieldPanel('title')]