add wordpress migration
This commit is contained in:
@ -0,0 +1,52 @@
|
||||
# Generated by Django 5.0.7 on 2024-08-06 14:25
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("events", "0046_eventpage_subtitle"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="eventpage",
|
||||
name="wp_block_json",
|
||||
field=models.TextField(blank=True, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="eventpage",
|
||||
name="wp_link",
|
||||
field=models.TextField(blank=True, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="eventpage",
|
||||
name="wp_normalized_styles",
|
||||
field=models.TextField(blank=True, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="eventpage",
|
||||
name="wp_post_id",
|
||||
field=models.IntegerField(blank=True, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="eventpage",
|
||||
name="wp_post_meta",
|
||||
field=models.JSONField(blank=True, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="eventpage",
|
||||
name="wp_post_type",
|
||||
field=models.CharField(blank=True, max_length=255, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="eventpage",
|
||||
name="wp_processed_content",
|
||||
field=models.TextField(blank=True, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="eventpage",
|
||||
name="wp_raw_content",
|
||||
field=models.TextField(blank=True, null=True),
|
||||
),
|
||||
]
|
19
dnscms/events/migrations/0048_alter_eventpage_body.py
Normal file
19
dnscms/events/migrations/0048_alter_eventpage_body.py
Normal file
@ -0,0 +1,19 @@
|
||||
# Generated by Django 5.0.7 on 2024-08-06 19:58
|
||||
|
||||
import wagtail.fields
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('events', '0047_eventpage_wp_block_json_eventpage_wp_link_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='eventpage',
|
||||
name='body',
|
||||
field=wagtail.fields.StreamField([('paragraph', 0), ('image', 4), ('image_slider', 8), ('horizontal_rule', 10), ('featured', 18), ('page_section_navigation', 19), ('accordion', 23), ('fact_box', 26), ('embed', 27), ('raw_html', 28)], block_lookup={0: ('wagtail.blocks.RichTextBlock', (), {'label': 'Rik tekst'}), 1: ('wagtail.images.blocks.ImageChooserBlock', (), {'label': 'Bilde'}), 2: ('wagtail.blocks.ChoiceBlock', [], {'choices': [('fullwidth', 'Fullbredde'), ('bleed', 'Utfallende'), ('original', 'Uendret størrelse')], 'icon': 'cup', 'label': 'Bildeformat'}), 3: ('wagtail.blocks.CharBlock', (), {'label': 'Bildetekst', 'max_length': 512, 'required': False}), 4: ('wagtail.blocks.StructBlock', [[('image', 1), ('image_format', 2), ('text', 3)]], {}), 5: ('wagtail.blocks.CharBlock', (), {'label': 'Tekst', 'max_length': 512, 'required': False}), 6: ('wagtail.blocks.StructBlock', [[('image', 1), ('text', 5)]], {}), 7: ('wagtail.blocks.ListBlock', (6,), {'label': 'Bilder', 'min_num': 1}), 8: ('wagtail.blocks.StructBlock', [[('images', 7)]], {}), 9: ('wagtail.blocks.ChoiceBlock', [], {'choices': [('deepBrick', 'Dyp tegl'), ('neufPink', 'Griserosa'), ('goldenOrange', 'Gyllen oransje'), ('goldenBeige', 'Gyllen beige'), ('chateauBlue', 'Slottsblå')], 'label': 'Farge', 'required': False}), 10: ('wagtail.blocks.StructBlock', [[('color', 9)]], {}), 11: ('wagtail.blocks.CharBlock', (), {'label': 'Tittel', 'max_length': 64, 'required': True}), 12: ('wagtail.blocks.RichTextBlock', (), {'features': ['bold', 'italic', 'link'], 'label': 'Tekst', 'required': True}), 13: ('wagtail.blocks.PageChooserBlock', (), {'header': 'Fremhevet side', 'required': True}), 14: ('wagtail.blocks.CharBlock', (), {'default': 'Les mer', 'help_text': 'Lenketeksten som tar deg videre til siden. Tips: Ikke start med "Trykk her"', 'label': 'Lenketekst', 'max_length': 64, 'required': True}), 15: ('wagtail.blocks.ChoiceBlock', [], {'choices': [('betongGray', 'Betonggrå'), ('deepBrick', 'Dyp tegl'), ('neufPink', 'Griserosa'), ('goldenOrange', 'Gyllen oransje'), ('goldenBeige', 'Gyllen beige'), ('chateauBlue', 'Slottsblå')], 'label': 'Bakgrunnsfarge'}), 16: ('wagtail.blocks.ChoiceBlock', [], {'choices': [('left', 'Venstre'), ('right', 'Høyre')], 'label': 'Bildeplassering'}), 17: ('wagtail.images.blocks.ImageChooserBlock', (), {'header': 'Overstyr bilde', 'help_text': 'Bildet som er tilknyttet undersiden du vil fremheve, vil automatisk brukes. Om det mangler eller du vil overstyre hvilket bilde som et brukes, kan du velge et her.', 'required': False}), 18: ('wagtail.blocks.StructBlock', [[('title', 11), ('text', 12), ('featured_page', 13), ('link_text', 14), ('background_color', 15), ('image_position', 16), ('featured_image_override', 17)]], {}), 19: ('dnscms.blocks.PageSectionNavigationBlock', (), {}), 20: ('wagtail.blocks.CharBlock', (), {'label': 'Overskrift', 'max_length': 64, 'required': True}), 21: ('wagtail.blocks.StructBlock', [[('image', 1), ('image_format', 2), ('text', 3)]], {'label': 'Bilde'}), 22: ('wagtail.blocks.StreamBlock', [[('paragraph', 0), ('image', 21)]], {}), 23: ('wagtail.blocks.StructBlock', [[('heading', 20), ('body', 22)]], {}), 24: ('wagtail.blocks.ChoiceBlock', [], {'choices': [('betongGray', 'Betonggrå'), ('deepBrick', 'Dyp tegl'), ('neufPink', 'Griserosa'), ('goldenOrange', 'Gyllen oransje'), ('goldenBeige', 'Gyllen beige'), ('chateauBlue', 'Slottsblå')], 'label': 'Bakgrunnsfarge', 'required': False}), 25: ('wagtail.blocks.RichTextBlock', (), {'features': ['bold', 'italic', 'link', 'ol', 'ul', 'h2', 'h3'], 'label': 'Innhold'}), 26: ('wagtail.blocks.StructBlock', [[('background_color', 24), ('body', 25)]], {}), 27: ('wagtail.embeds.blocks.EmbedBlock', (), {}), 28: ('wagtail.blocks.RawHTMLBlock', (), {})}, default=[('paragraph', '')]),
|
||||
),
|
||||
]
|
@ -0,0 +1,23 @@
|
||||
# Generated by Django 5.0.7 on 2024-08-06 23:25
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('events', '0048_alter_eventpage_body'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='eventpage',
|
||||
name='facebook_url',
|
||||
field=models.URLField(blank=True, help_text='Lenke direkte til arrangementet på Facebook', max_length=1024),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='eventpage',
|
||||
name='ticket_url',
|
||||
field=models.URLField(blank=True, help_text='Lenke direkte til billettkjøp, f.eks. TicketCo eller Ticketmaster', max_length=1024),
|
||||
),
|
||||
]
|
@ -0,0 +1,18 @@
|
||||
# Generated by Django 5.0.7 on 2024-08-07 20:29
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('events', '0049_alter_eventpage_facebook_url_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='eventoccurrence',
|
||||
name='venue_custom',
|
||||
field=models.CharField(blank=True, help_text='Bruk denne <em>om ingen av lokalene som kan velges ovenfor</em> passer.F.eks. <em>Chateau Neuf</em> eller <em>Frederikkeplassen</em>.', max_length=128),
|
||||
),
|
||||
]
|
@ -0,0 +1,25 @@
|
||||
# Generated by Django 5.0.7 on 2024-08-07 20:56
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('events', '0050_eventoccurrence_venue_custom'),
|
||||
('venues', '0021_venuepage_tech_specs_url'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='eventoccurrence',
|
||||
name='venue',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='event_occurrences', to='venues.venuepage'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='eventoccurrence',
|
||||
name='venue_custom',
|
||||
field=models.CharField(blank=True, help_text='Bruk denne <em>om ingen av lokalene som kan velges til venstre</em> passer. F.eks. <em>Frederikkeplassen</em> eller <em>Sirkusteltet</em>.', max_length=128),
|
||||
),
|
||||
]
|
@ -0,0 +1,31 @@
|
||||
# Generated by Django 5.0.7 on 2024-08-07 22:05
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('events', '0051_alter_eventoccurrence_venue_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='eventpage',
|
||||
name='price_member',
|
||||
field=models.CharField(blank=True, default='', max_length=32),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='eventpage',
|
||||
name='price_regular',
|
||||
field=models.CharField(blank=True, default='', max_length=32),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='eventpage',
|
||||
name='price_student',
|
||||
field=models.CharField(blank=True, default='', max_length=32),
|
||||
preserve_default=False,
|
||||
),
|
||||
]
|
@ -1,7 +1,9 @@
|
||||
from django import forms
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.db import models
|
||||
from django.db.models import Min, Q, UniqueConstraint
|
||||
from django.utils import timezone
|
||||
from django.utils.html import mark_safe
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from grapple.helpers import register_query_field, register_singular_query_field
|
||||
from grapple.models import (
|
||||
@ -9,7 +11,6 @@ from grapple.models import (
|
||||
GraphQLCollection,
|
||||
GraphQLForeignKey,
|
||||
GraphQLImage,
|
||||
GraphQLInt,
|
||||
GraphQLStreamfield,
|
||||
GraphQLString,
|
||||
)
|
||||
@ -27,6 +28,7 @@ from wagtail.admin.panels import (
|
||||
from wagtail.models import Orderable, Page, PageManager, PageQuerySet
|
||||
from wagtail.search import index
|
||||
from wagtail.snippets.models import register_snippet
|
||||
from wagtail_wordpress_import.models import WPImportedPageMixin
|
||||
|
||||
from associations.widgets import AssociationChooserWidget
|
||||
from dnscms.fields import CommonStreamField
|
||||
@ -226,7 +228,7 @@ class EventPageQuerySet(PageQuerySet):
|
||||
EventPageManager = PageManager.from_queryset(EventPageQuerySet)
|
||||
|
||||
|
||||
class EventPage(Page):
|
||||
class EventPage(WPImportedPageMixin, Page):
|
||||
subpage_types = []
|
||||
parent_page_types = ["events.EventIndex"]
|
||||
show_in_menus = False
|
||||
@ -283,19 +285,19 @@ class EventPage(Page):
|
||||
|
||||
ticket_url = models.URLField(
|
||||
blank=True,
|
||||
max_length=512,
|
||||
max_length=1024,
|
||||
help_text="Lenke direkte til billettkjøp, f.eks. TicketCo eller Ticketmaster",
|
||||
)
|
||||
facebook_url = models.URLField(
|
||||
blank=True,
|
||||
max_length=512,
|
||||
max_length=1024,
|
||||
help_text="Lenke direkte til arrangementet på Facebook",
|
||||
)
|
||||
|
||||
free = models.BooleanField(null=False, default=False)
|
||||
price_regular = models.IntegerField(null=True, blank=True)
|
||||
price_student = models.IntegerField(null=True, blank=True)
|
||||
price_member = models.IntegerField(null=True, blank=True)
|
||||
price_regular = models.CharField(max_length=32, blank=True)
|
||||
price_student = models.CharField(max_length=32, blank=True)
|
||||
price_member = models.CharField(max_length=32, blank=True)
|
||||
|
||||
ticket_panels = [
|
||||
FieldPanel("free", heading="Gratis", help_text="Er dette arrangementet gratis for alle?"),
|
||||
@ -309,7 +311,11 @@ class EventPage(Page):
|
||||
],
|
||||
help_text="",
|
||||
),
|
||||
HelpPanel(content="La alle prisfeltene stå tomme om arrangementet er gratis."),
|
||||
HelpPanel(
|
||||
content=mark_safe(
|
||||
"Skriv <strong>0</strong> om gratis. Tomt felt skjuler priskategorien. Om mulig, skriv kun tall."
|
||||
)
|
||||
),
|
||||
],
|
||||
attrs={"id": "specific_pricing_panel"},
|
||||
),
|
||||
@ -328,7 +334,7 @@ class EventPage(Page):
|
||||
content=("Hvem står bak arrangementet?"),
|
||||
),
|
||||
MultipleChooserPanel(
|
||||
"organizer_links", chooser_field_name="organizer", min_num=1, label="Arrangør"
|
||||
"organizer_links", chooser_field_name="organizer", label="Arrangør"
|
||||
),
|
||||
],
|
||||
),
|
||||
@ -361,9 +367,9 @@ class EventPage(Page):
|
||||
GraphQLString("ticket_url"),
|
||||
GraphQLString("facebook_url"),
|
||||
GraphQLBoolean("free"),
|
||||
GraphQLInt("price_regular"),
|
||||
GraphQLInt("price_student"),
|
||||
GraphQLInt("price_member"),
|
||||
GraphQLString("price_regular"),
|
||||
GraphQLString("price_student"),
|
||||
GraphQLString("price_member"),
|
||||
GraphQLCollection(
|
||||
GraphQLForeignKey,
|
||||
"categories",
|
||||
@ -404,9 +410,133 @@ class EventPage(Page):
|
||||
|
||||
# if the event is free, all specific pricing is unset
|
||||
if self.free:
|
||||
self.price_regular = None
|
||||
self.price_student = None
|
||||
self.price_member = None
|
||||
self.price_regular = ""
|
||||
self.price_student = ""
|
||||
self.price_member = ""
|
||||
|
||||
settings_panels = Page.settings_panels + WPImportedPageMixin.wordpress_panels
|
||||
|
||||
def import_wordpress_data(self, data):
|
||||
import datetime
|
||||
import html
|
||||
|
||||
from django.core.validators import URLValidator
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
validate_url = URLValidator(schemes=["http", "https"])
|
||||
|
||||
def fix_url(url):
|
||||
if not url:
|
||||
return None
|
||||
url = url.strip()
|
||||
try:
|
||||
validate_url(url)
|
||||
except Exception:
|
||||
print(f"Bogus URL for {self.wp_post_id}: {url}")
|
||||
return None
|
||||
return url
|
||||
|
||||
# Wagtail page model fields
|
||||
self.title = html.unescape(data["title"])
|
||||
self.slug = data["slug"]
|
||||
self.first_published_at = data["first_published_at"]
|
||||
self.last_published_at = data["last_published_at"]
|
||||
self.latest_revision_created_at = data["latest_revision_created_at"]
|
||||
self.search_description = data["search_description"]
|
||||
|
||||
# debug fields
|
||||
self.wp_post_id = data["wp_post_id"]
|
||||
self.wp_post_type = data["wp_post_type"]
|
||||
self.wp_link = data["wp_link"]
|
||||
self.wp_raw_content = data["wp_raw_content"]
|
||||
self.wp_block_json = data["wp_block_json"]
|
||||
self.wp_processed_content = data["wp_processed_content"]
|
||||
self.wp_normalized_styles = data["wp_normalized_styles"]
|
||||
self.wp_post_meta = data["wp_post_meta"]
|
||||
|
||||
# own model fields
|
||||
self.body = data["body"] or ""
|
||||
|
||||
# categories (organizers and event types)
|
||||
wp_categories = data["wp_categories"]
|
||||
|
||||
# organizers
|
||||
organizer_cats = [x for x in wp_categories if x["domain"] == "event_organizer"]
|
||||
organizers = []
|
||||
for x in organizer_cats:
|
||||
try:
|
||||
organizer = EventOrganizer.objects.get(slug=x["nicename"])
|
||||
except EventOrganizer.DoesNotExist:
|
||||
organizer = EventOrganizer.objects.create(name=x["name"], slug=x["nicename"])
|
||||
organizers.append(organizer)
|
||||
|
||||
self.organizer_links.set(
|
||||
[EventOrganizerLink(event=self, organizer=organizer) for organizer in organizers]
|
||||
)
|
||||
|
||||
## event types
|
||||
# type_cats = [x for x in wp_categories if x["domain"] == "event_type"]
|
||||
# event_categories = []
|
||||
# for x in type_cats:
|
||||
# try:
|
||||
# event_category = EventCategory.objects.get(slug=x["nicename"])
|
||||
# except EventCategory.DoesNotExist:
|
||||
# event_category = EventCategory.objects.create(
|
||||
# name=x["name"], slug=x["nicename"], show_in_filters=False
|
||||
# )
|
||||
# event_categories.append(event_category)
|
||||
# self.categories.set(event_categories)
|
||||
|
||||
meta = data["wp_post_meta"]
|
||||
|
||||
start_ts = meta.get("neuf_events_starttime") or 1337
|
||||
end_ts = meta.get("neuf_events_endtime")
|
||||
tz = ZoneInfo("Europe/Oslo")
|
||||
start = start_ts and datetime.datetime.fromtimestamp(start_ts, datetime.UTC).replace(
|
||||
tzinfo=tz
|
||||
)
|
||||
end = end_ts and datetime.datetime.fromtimestamp(end_ts, datetime.UTC).replace(tzinfo=tz)
|
||||
venue_id = meta.get("neuf_events_venue_id")
|
||||
venue_custom = meta.get("neuf_events_venue")
|
||||
venue = None
|
||||
if venue_id:
|
||||
venue = VenuePage.objects.get(wp_post_id=venue_id)
|
||||
venue_custom = ""
|
||||
else:
|
||||
venue_custom = venue_custom or ""
|
||||
|
||||
occurrence = EventOccurrence(
|
||||
event=self, start=start, end=end, venue=venue, venue_custom=venue_custom
|
||||
)
|
||||
self.occurrences.set([occurrence])
|
||||
|
||||
self.ticket_url = fix_url(meta.get("neuf_events_bs_url")) or ""
|
||||
self.facebook_url = fix_url(meta.get("neuf_events_fb_url")) or ""
|
||||
|
||||
def parse_price(price):
|
||||
if price is None:
|
||||
return ""
|
||||
if type(price) is int:
|
||||
return price
|
||||
p = price.strip()
|
||||
if p == "":
|
||||
return ""
|
||||
try:
|
||||
return int(p)
|
||||
except ValueError:
|
||||
pass
|
||||
free = ["gratis", "free", "gratis/free", "free/gratis"]
|
||||
if p.lower() in free:
|
||||
return 0
|
||||
return price
|
||||
|
||||
price_regular = parse_price(meta.get("neuf_events_price_regular"))
|
||||
price_member = parse_price(meta.get("neuf_events_price_member"))
|
||||
if not price_regular and not price_member:
|
||||
self.free = True
|
||||
else:
|
||||
self.price_regular = parse_price(meta.get("neuf_events_price_regular"))
|
||||
self.price_member = parse_price(meta.get("neuf_events_price_member"))
|
||||
|
||||
|
||||
class EventOccurrence(Orderable):
|
||||
@ -414,7 +544,19 @@ class EventOccurrence(Orderable):
|
||||
start = models.DateTimeField()
|
||||
end = models.DateTimeField(null=True, blank=True)
|
||||
venue = models.ForeignKey(
|
||||
VenuePage, on_delete=models.PROTECT, related_name="event_occurrences"
|
||||
VenuePage,
|
||||
on_delete=models.PROTECT,
|
||||
related_name="event_occurrences",
|
||||
blank=True,
|
||||
null=True,
|
||||
)
|
||||
venue_custom = models.CharField(
|
||||
blank=True,
|
||||
max_length=128,
|
||||
help_text=mark_safe(
|
||||
"Bruk denne <em>om ingen av lokalene som kan velges til venstre</em> passer. "
|
||||
"F.eks. <em>Frederikkeplassen</em> eller <em>Sirkusteltet</em>."
|
||||
),
|
||||
)
|
||||
|
||||
panels = [
|
||||
@ -424,7 +566,12 @@ class EventOccurrence(Orderable):
|
||||
FieldPanel("end", heading="Slutt"),
|
||||
],
|
||||
),
|
||||
FieldPanel("venue", heading="Lokale"),
|
||||
FieldRowPanel(
|
||||
children=[
|
||||
FieldPanel("venue", heading="Lokale"),
|
||||
FieldPanel("venue_custom", heading="Lokale som fritekst"),
|
||||
],
|
||||
),
|
||||
]
|
||||
|
||||
graphql_fields = [
|
||||
@ -433,6 +580,14 @@ class EventOccurrence(Orderable):
|
||||
GraphQLForeignKey("venue", "venues.VenuePage"),
|
||||
]
|
||||
|
||||
def clean(self):
|
||||
if self.venue and self.venue_custom:
|
||||
raise ValidationError(
|
||||
{"venue_custom": "Du kan ikke både velge et lokale og skrive noe i dette feltet."}
|
||||
)
|
||||
if not self.venue and not self.venue_custom:
|
||||
raise ValidationError({"venue": "Lokale er påkrevd."})
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.start}--{self.end}"
|
||||
|
||||
|
Reference in New Issue
Block a user