from datetime import date
from crispy_forms.utils import flatatt
from django.db import models
import django.db.models.options as options
from django.utils.html import format_html, format_html_join
from wagtail.embeds.blocks import EmbedBlock
options.DEFAULT_NAMES = options.DEFAULT_NAMES + ('description',)
from django.urls import reverse
from django.contrib import messages
from wagtailcaptcha.models import WagtailCaptchaEmailForm
from crispy_forms.helper import FormHelper
from django_extensions.db.models import TimeStampedModel
from modelcluster.fields import ParentalKey
from wagtail import blocks
from wagtail.documents import get_document_model
from wagtail.images import get_image_model
from wagtail.models import Page
from wagtail.fields import RichTextField, StreamField
from wagtail.admin.panels import (
MultiFieldPanel, PageChooserPanel, InlinePanel, FieldPanel)
from wagtail.images.blocks import ImageChooserBlock
from wagtail.documents.blocks import DocumentChooserBlock
from wagtail.contrib.forms.models import AbstractEmailForm, AbstractFormField
from wagtailmedia.edit_handlers import MediaChooserPanel
from wagtailmedia.blocks import AbstractMediaChooserBlock
class MediaBlock(AbstractMediaChooserBlock):
def render_basic(self, value, context=None):
if not value:
return ''
if value.type == 'video':
player_code = '''
{0}
Your browser does not support the video tag.
'''
else:
player_code = '''
{0}
Your browser does not support the audio element.
'''
return format_html(player_code, format_html_join(
'\n', "",
[[flatatt(s)] for s in value.sources]
))
class HomePage(Page):
block1 = RichTextField(blank=True)
# revolution slider
slide1_img = models.ForeignKey(
get_image_model(),
null=True,
blank=True,
on_delete=models.SET_NULL,
related_name='+'
)
slide1_headline = models.CharField(max_length=512, blank=True)
slide1_subline = models.CharField(max_length=512, blank=True)
slide1_link_url = models.URLField(blank=True)
slide1_link_text = models.CharField(max_length=64, blank=True)
slide2_img = models.ForeignKey(
get_image_model(),
null=True,
blank=True,
on_delete=models.SET_NULL,
related_name='+'
)
slide2_headline = models.CharField(max_length=512, blank=True)
slide2_subline = models.CharField(max_length=512, blank=True)
slide2_link_url = models.URLField(blank=True)
slide2_link_text = models.CharField(max_length=64, blank=True)
slide3_img = models.ForeignKey(
get_image_model(),
null=True,
blank=True,
on_delete=models.SET_NULL,
related_name='+'
)
slide3_headline = models.CharField(max_length=512, blank=True)
slide3_subline = models.CharField(max_length=512, blank=True)
slide3_link_url = models.URLField(blank=True)
slide3_link_text = models.CharField(max_length=64, blank=True)
thumbnail1_img = models.ForeignKey(
get_image_model(),
null=True,
blank=True,
on_delete=models.SET_NULL,
related_name='+'
)
thumbnail1_more_page = models.ForeignKey(
'wagtailcore.Page',
null=True,
blank=True,
on_delete=models.SET_NULL,
related_name='+',
)
thumbnail1_more_text = models.CharField(max_length=64, blank=True)
thumbnail1_title = models.CharField(max_length=128, blank=True)
thumbnail1_text = RichTextField(blank=True)
thumbnail2_img = models.ForeignKey(
get_image_model(),
null=True,
blank=True,
on_delete=models.SET_NULL,
related_name='+'
)
thumbnail2_more_page = models.ForeignKey(
'wagtailcore.Page',
null=True,
blank=True,
on_delete=models.SET_NULL,
related_name='+',
)
thumbnail2_more_text = models.CharField(max_length=64, blank=True)
thumbnail2_title = models.CharField(max_length=128, blank=True)
thumbnail2_text = RichTextField(blank=True)
thumbnail3_img = models.ForeignKey(
get_image_model(),
null=True,
blank=True,
on_delete=models.SET_NULL,
related_name='+'
)
thumbnail3_more_page = models.ForeignKey(
'wagtailcore.Page',
null=True,
blank=True,
on_delete=models.SET_NULL,
related_name='+',
)
thumbnail3_more_text = models.CharField(max_length=64, blank=True)
thumbnail3_title = models.CharField(max_length=128, blank=True)
thumbnail3_text = RichTextField(blank=True)
REVOLUTION_SLIDER_FIELDS = [
MultiFieldPanel([
FieldPanel('slide1_img'),
FieldPanel('slide1_headline', classname="full"),
FieldPanel('slide1_subline', classname="full"),
FieldPanel('slide1_link_url', classname="full"),
FieldPanel('slide1_link_text', classname="full"),
], heading='Slide 1', classname="collapsible"),
MultiFieldPanel([
FieldPanel('slide2_img'),
FieldPanel('slide2_headline', classname="full"),
FieldPanel('slide2_subline', classname="full"),
FieldPanel('slide2_link_url', classname="full"),
FieldPanel('slide2_link_text', classname="full"),
], heading='Slide 2', classname="collapsible"),
MultiFieldPanel([
FieldPanel('slide3_img'),
FieldPanel('slide3_headline', classname="full"),
FieldPanel('slide3_subline', classname="full"),
FieldPanel('slide3_link_url', classname="full"),
FieldPanel('slide3_link_text', classname="full"),
], heading='Slide 3'),
]
HOME_THUMBNAIL_FIELDS = [
MultiFieldPanel([
FieldPanel('thumbnail1_img'),
PageChooserPanel('thumbnail1_more_page'),
FieldPanel('thumbnail1_more_text', classname="full"),
FieldPanel('thumbnail1_title', classname="full"),
FieldPanel('thumbnail1_text', classname="full"),
], heading='Thumbnail 1', classname="collapsible"),
MultiFieldPanel([
FieldPanel('thumbnail2_img'),
PageChooserPanel('thumbnail2_more_page'),
FieldPanel('thumbnail2_more_text', classname="full"),
FieldPanel('thumbnail2_title', classname="full"),
FieldPanel('thumbnail2_text', classname="full"),
], heading='Thumbnail 2', classname="collapsible"),
MultiFieldPanel([
FieldPanel('thumbnail3_img'),
PageChooserPanel('thumbnail3_more_page'),
FieldPanel('thumbnail3_more_text', classname="full"),
FieldPanel('thumbnail3_title', classname="full"),
FieldPanel('thumbnail3_text', classname="full"),
], heading='Thumbnail 3', classname="collapsible"),
]
HomePage.content_panels = [
FieldPanel('title', classname="full title"),
MultiFieldPanel(REVOLUTION_SLIDER_FIELDS, heading='Slider elements', classname="collapsible collapsed"),
FieldPanel('block1', classname="full"),
MultiFieldPanel(HOME_THUMBNAIL_FIELDS, heading='Thumbnail elements', classname="collapsible collapsed"),
]
class SimpleOneColumnPage(Page):
featured_media = models.ForeignKey(
'wagtailmedia.Media',
null=True,
blank=True,
on_delete=models.SET_NULL,
related_name='+'
)
content = RichTextField(blank=True)
SimpleOneColumnPage.content_panels = [
FieldPanel('title', classname="full title"),
FieldPanel('featured_media'),
FieldPanel('content', classname="full"),
]
class BlogPage(Page):
posts = StreamField([
('post', blocks.StructBlock([
('images', blocks.ListBlock(ImageChooserBlock())),
('title', blocks.CharBlock(max_length=200)),
('author', blocks.CharBlock(max_length=64, default="Marion Schauf", required=False)),
('date', blocks.DateBlock()),
('text', blocks.RichTextBlock()),
('url', blocks.URLBlock(required=False)),
])),
], null=True, blank=True, use_json_field=True)
BlogPage.content_panels = [
FieldPanel('title', classname="full title"),
FieldPanel('posts'),
]
class EventIndexPage(Page):
subpage_types = ['core.EventPage']
def get_events(self):
return EventPage.objects.live().filter(show_in_event_calendar=True, path__startswith=self.path).order_by('start_date')
class Meta:
description = "Displays all events on EventPages below in an overview. Use this as parent page for events."
class EventPage(AbstractEmailForm):
parent_page_types = ['core.EventIndexPage', 'core.EventHistoryPage']
subtitle = models.CharField(max_length=512, null=True, blank=True)
description = RichTextField(blank=True)
# revolution slider
slide1_img = models.ForeignKey(
get_image_model(),
null=True,
blank=True,
on_delete=models.SET_NULL,
related_name='+'
)
slide1_headline = models.CharField(max_length=512, blank=True)
slide1_subline = models.CharField(max_length=512, blank=True)
slide1_link_url = models.URLField(blank=True)
slide1_link_text = models.CharField(max_length=64, blank=True)
slide2_img = models.ForeignKey(
get_image_model(),
null=True,
blank=True,
on_delete=models.SET_NULL,
related_name='+'
)
slide2_headline = models.CharField(max_length=512, blank=True)
slide2_subline = models.CharField(max_length=512, blank=True)
slide2_link_url = models.URLField(blank=True)
slide2_link_text = models.CharField(max_length=64, blank=True)
slide3_img = models.ForeignKey(
get_image_model(),
null=True,
blank=True,
on_delete=models.SET_NULL,
related_name='+'
)
slide3_headline = models.CharField(max_length=512, blank=True)
slide3_subline = models.CharField(max_length=512, blank=True)
slide3_link_url = models.URLField(blank=True)
slide3_link_text = models.CharField(max_length=64, blank=True)
img1_img = models.ForeignKey(
get_image_model(),
null=True,
blank=True,
on_delete=models.SET_NULL,
related_name='+'
)
img1_caption = models.CharField(max_length=64, blank=True)
img2_img = models.ForeignKey(
get_image_model(),
null=True,
blank=True,
on_delete=models.SET_NULL,
related_name='+'
)
img2_caption = models.CharField(max_length=64, blank=True)
start_date = models.DateField()
end_date = models.DateField(null=True, blank=True)
location_name = models.CharField(
max_length=256, help_text="Name of the location (first line of address)", blank=True)
location_street = models.CharField(max_length=256, help_text="Street and house number", blank=True)
location_city = models.CharField(max_length=256, help_text="Zip code and city", blank=True)
flyer = models.ForeignKey(
get_document_model(),
null=True,
blank=True,
on_delete=models.SET_NULL,
related_name='+'
)
downloads = StreamField([
('download', blocks.StructBlock([
('title', blocks.CharBlock(max_length=128, label='Name (Button-Beschriftung)')),
('file', DocumentChooserBlock(label='Datei')),
])),
], null=True, blank=True, use_json_field=True)
tabs = StreamField([
('sponsor_tab', blocks.StructBlock([
('title', blocks.CharBlock(max_length=64)),
('sponsors', blocks.StreamBlock([
('sponsor', blocks.StructBlock([
('name', blocks.CharBlock(max_length=64)),
('logo', ImageChooserBlock(required=False)),
('url', blocks.URLBlock(required=False)),
])),
('headline', blocks.CharBlock(max_length=64)),
])),
])),
('richtext_tab', blocks.StructBlock([
('title', blocks.CharBlock(max_length=64)),
('content', blocks.RichTextBlock()),
])),
('media_tab', blocks.StructBlock([
('title', blocks.CharBlock(max_length=64)),
('pre_content', blocks.RichTextBlock(required=False)),
('media_file', MediaBlock(template='core/blocks/media_block.html')),
('autoplay', blocks.BooleanBlock(label='Automatisch abspielen', required=False)),
('muted', blocks.BooleanBlock(label='Stummgeschaltet starten', required=False)),
('post_content', blocks.RichTextBlock(required=False)),
])),
], null=True, blank=True, use_json_field=True)
registration_url = models.URLField(max_length=512, blank=True, help_text="URL der Anmeldeseite (leer lassen um klassische Anmeldung zu verwenden)")
pretix_slug = models.CharField(max_length=512, blank=True, help_text="Slug von Pretix (leer lassen, um klassische Anmeldung zu verwenden)")
registration_start_date = models.DateField(
null=True, blank=True, help_text="When does the registration open? Leave empty to disable registration")
registration_end_date = models.DateField(
null=True, blank=True,
help_text="Last day where the registration will be available. Leave empty to enable registration permanently"
"after start date")
show_in_event_calendar = models.BooleanField(default=True, help_text='Event in Eventliste und im Kalender anzeigen?')
is_free = models.BooleanField(default=False, help_text='If this is checked the send button under the registration'
'form will be labeled "verbindlich anmelden" instead of "kostenpflichtig anmelden"')
external_registration_code = models.TextField(
blank=True, null=True,
help_text='Put code e.g. from Xing here. If this field is filled out there will be no registration form displayed.')
vimeo_id = models.TextField(blank=True, help_text='Vimeo Event ID (aus Vimeo-Link: https://vimeo.com/ )')
def is_registration_active(self):
return self.registration_start_date and self.registration_start_date <= date.today() and\
(not self.registration_end_date or self.registration_end_date >= date.today())
@property
def pretix_url(self):
if self.pretix_slug:
return 'https://tickets.feo.gmbh/' + self.pretix_slug + '/'
return None
def get_form_helper(self):
helper = FormHelper()
helper.label_class = 'col-lg-3'
helper.field_class = 'col-lg-9'
helper.form_tag = False
return helper
class Meta:
ordering = ['-start_date']
class EventRegistrationField(AbstractFormField):
page = ParentalKey('EventPage', related_name='form_fields')
EventPage.content_panels = [
MultiFieldPanel(REVOLUTION_SLIDER_FIELDS, heading='Slider elements', classname="collapsible collapsed"),
FieldPanel('title', classname="full title"),
FieldPanel('subtitle', classname="full"),
FieldPanel('description', classname="full"),
FieldPanel('img1_img'),
FieldPanel('img1_caption', classname="full"),
FieldPanel('img2_img'),
FieldPanel('img2_caption', classname="full"),
FieldPanel('start_date', classname="full"),
FieldPanel('end_date', classname="full"),
FieldPanel('tabs'),
FieldPanel('location_name', classname="full"),
FieldPanel('location_street', classname="full"),
FieldPanel('location_city', classname="full"),
FieldPanel('flyer'),
FieldPanel('downloads'),
MultiFieldPanel([
FieldPanel('show_in_event_calendar', classname="full"),
FieldPanel('is_free', classname="full"),
FieldPanel('pretix_slug', classname="full"),
FieldPanel('registration_url', classname="full"),
FieldPanel('vimeo_id', classname="full"),
], heading="Settings", classname="collapsible collapsed"),
FieldPanel('external_registration_code', classname="full"),
MultiFieldPanel([
InlinePanel('form_fields', label="Form fields"),
FieldPanel('registration_start_date', classname="full"),
FieldPanel('registration_end_date', classname="full"),
MultiFieldPanel([
FieldPanel('to_address', classname="full"),
FieldPanel('from_address', classname="full"),
FieldPanel('subject', classname="full"),
], "Email"),
], heading="Registration Form", classname="collapsible collapsed"),
]
class EventHistoryPage(Page):
events = StreamField([
('event', blocks.StructBlock([
('title', blocks.CharBlock(max_length=512, required=False)),
('subtitle', blocks.CharBlock(max_length=512, required=False)),
('start_date', blocks.DateBlock()),
('end_date', blocks.DateBlock(required=False, help_text="Leave empty for single day events")),
('location_name', blocks.CharBlock(
max_length=256, help_text="Name of the location (first line of address)", required=False)),
('location_city', blocks.CharBlock(max_length=256, help_text="Zip code and city", required=False)),
('image', ImageChooserBlock(required=False)),
('flyer', DocumentChooserBlock(required=False)),
('additional_info_btn_label', blocks.CharBlock(max_length=128, required=False, label='Zusatzinfo Button Text')),
('additional_info_target', blocks.PageChooserBlock(required=False, label='Zusatzinfo Zielseite')),
])),
], null=True, blank=True, use_json_field=True)
EventHistoryPage.content_panels = [
FieldPanel('title', classname="full title"),
FieldPanel('events'),
]
class ContactFormField(AbstractFormField):
page = ParentalKey('ContactFormPage', related_name='form_fields')
class ContactFormPage(WagtailCaptchaEmailForm):
form_title = models.CharField(max_length=128, blank=True)
person_img = models.ForeignKey(
get_image_model(),
null=True,
blank=True,
on_delete=models.SET_NULL,
related_name='+'
)
person_name = models.CharField(max_length=128, blank=True)
person_position = models.CharField(max_length=128, blank=True)
address = models.CharField(max_length=128, blank=True)
mail_address = models.CharField(max_length=128, blank=True)
phone = models.CharField(max_length=128, blank=True)
web_address = models.URLField(blank=True)
thank_you_text = RichTextField(blank=True)
ContactFormPage.content_panels = [
FieldPanel('title', classname="full title"),
FieldPanel('form_title', classname="full"),
FieldPanel('person_img'),
FieldPanel('person_name', classname="full"),
FieldPanel('person_position', classname="full"),
FieldPanel('address', classname="full"),
FieldPanel('mail_address', classname="full"),
FieldPanel('phone', classname="full"),
FieldPanel('web_address', classname="full"),
InlinePanel('form_fields', label="Form fields"),
FieldPanel('thank_you_text', classname="full"),
MultiFieldPanel([
FieldPanel('to_address', classname="full"),
FieldPanel('from_address', classname="full"),
FieldPanel('subject', classname="full"),
], "Email")
]
class UploadedScript(TimeStampedModel):
name = models.CharField(max_length=512, verbose_name='Ihr Name')
script = models.FileField(upload_to='scripts', verbose_name='Skript')
def get_delete_url(self):
return reverse('delete_script', kwargs={'pk': self.pk})
def delete(self, *args, **kwargs):
storage, path = self.script.storage, self.script.path
out = super().delete(*args, **kwargs)
storage.delete(path)
return out