From daa30d9f799df2f41717ab5b451fbe776ad93938 Mon Sep 17 00:00:00 2001 From: Magnus Hagander Date: Wed, 21 Aug 2024 13:47:55 +0200 Subject: [PATCH] List which fields are available when building tweet templates Both for sponsor benefits and for campaign creation, list which fields are available to use in the Jinja templates, to make it easier to figure out how to use them. --- postgresqleu/confreg/campaigns.py | 27 +++++++++++++++++++++--- postgresqleu/confsponsor/backendforms.py | 22 +++++++++++++++---- postgresqleu/confsponsor/models.py | 5 +++++ 3 files changed, 47 insertions(+), 7 deletions(-) diff --git a/postgresqleu/confreg/campaigns.py b/postgresqleu/confreg/campaigns.py index 456aee56..0230ddcc 100644 --- a/postgresqleu/confreg/campaigns.py +++ b/postgresqleu/confreg/campaigns.py @@ -4,10 +4,11 @@ from django.http import Http404, HttpResponse from django.utils.dateparse import parse_datetime, parse_duration from django.utils import timezone -from postgresqleu.util.widgets import MonospaceTextarea -from postgresqleu.confreg.models import ConferenceSession, Track +from postgresqleu.util.widgets import MonospaceTextarea, SimpleTreeviewWidget +from postgresqleu.confreg.models import Conference, ConferenceSession, Track from postgresqleu.confreg.models import MessagingProvider from postgresqleu.confreg.twitter import post_conference_social, render_multiprovider_tweet +from postgresqleu.confreg.jinjafunc import get_all_available_attributes from postgresqleu.confsponsor.models import Sponsor, SponsorshipLevel from postgresqleu.util.messaging import get_messaging, get_messaging_class from postgresqleu.util.messaging.short import get_shortened_post_length @@ -54,16 +55,19 @@ class BaseCampaignForm(forms.Form): content_template = forms.CharField(max_length=2000, widget=MonospaceTextarea, required=True) + available_fields = forms.CharField(required=False, help_text="These fields are available as {{field}} in the template") dynamic_preview_fields = ['content_template', ] confirm = forms.BooleanField(help_text="Confirm that you want to generate all the tweets for this campaign at this time", required=False) def __init__(self, conference, *args, **kwargs): self.conference = conference - self.field_order = ['starttime', 'timebetween', 'timerandom', 'content_template'] + self.custom_fields + ['confirm', ] + self.field_order = ['starttime', 'timebetween', 'timerandom', 'content_template', 'available_fields', ] + self.custom_fields + ['confirm', ] super(BaseCampaignForm, self).__init__(*args, *kwargs) + self.fields['available_fields'].widget = SimpleTreeviewWidget(treedata=self.get_contextrefs()) + if not all([self.data.get(f) for f in ['starttime', 'timebetween', 'timerandom', 'content_template'] + self.custom_fields]): del self.fields['confirm'] else: @@ -80,6 +84,9 @@ class BaseCampaignForm(forms.Form): else: self.fields['confirm'].help_text = "Campaign matches no entries. Try again." + def get_contextrefs(self): + return {} + def clean_confirm(self): if not self.cleaned_data['confirm']: if self.get_queryset().count == 0: @@ -119,6 +126,13 @@ class ApprovedSessionsCampaignForm(BaseCampaignForm): 'session': session, }) + @classmethod + def get_contextrefs(cls): + return { + 'conference': dict(get_all_available_attributes(Conference)), + 'session': dict(get_all_available_attributes(ConferenceSession)), + } + def get_queryset(self): return ConferenceSession.objects.filter(conference=self.conference, status=1, cross_schedule=False, track__in=self.data.getlist('tracks')) @@ -139,6 +153,13 @@ class SponsorsCampaignForm(BaseCampaignForm): 'sponsor': sponsor, }) + @classmethod + def get_contextrefs(cls): + return { + 'conference': dict(get_all_available_attributes(Conference)), + 'sponsor': dict(get_all_available_attributes(Sponsor)), + } + def get_queryset(self): return Sponsor.objects.filter(conference=self.conference, confirmed=True, level__in=self.data.getlist('levels')) diff --git a/postgresqleu/confsponsor/backendforms.py b/postgresqleu/confsponsor/backendforms.py index 731a65fa..d85656a1 100644 --- a/postgresqleu/confsponsor/backendforms.py +++ b/postgresqleu/confsponsor/backendforms.py @@ -7,14 +7,16 @@ from collections import OrderedDict import json from postgresqleu.util.db import exec_to_scalar -from postgresqleu.util.widgets import StaticTextWidget +from postgresqleu.util.widgets import StaticTextWidget, SimpleTreeviewWidget from postgresqleu.util.widgets import MonospaceTextarea from postgresqleu.util.backendforms import BackendForm, BackendBeforeNewForm from postgresqleu.util.backendlookups import GeneralAccountLookup from postgresqleu.confreg.jinjafunc import JinjaTemplateValidator, filter_social +from postgresqleu.confreg.jinjafunc import get_all_available_attributes from postgresqleu.confreg.twitter import get_all_conference_social_media from postgresqleu.confreg.twitter import render_multiprovider_tweet +from postgresqleu.confreg.models import Conference from .models import Sponsor from .models import SponsorshipLevel, SponsorshipContract, SponsorshipBenefit from .models import ShipmentAddress @@ -107,12 +109,13 @@ class BackendSponsorshipLevelBenefitForm(BackendForm): markdown_fields = ['benefitdescription', 'claimprompt', ] dynamic_preview_fields = ['tweet_template'] form_before_new = BackendSponsorshipNewBenefitForm - readonly_fields = ['benefit_class_name', ] + readonly_fields = ['benefit_class_name', 'available_fields', ] exclude_date_validators = ['deadline', ] class_param_fields = [] # Overridden in subclass! benefit_class_name = django.forms.CharField(required=False) + available_fields = django.forms.CharField(required=False) @property def fieldsets(self): @@ -125,7 +128,7 @@ class BackendSponsorshipLevelBenefitForm(BackendForm): return [ {'id': 'base', 'legend': 'Base', 'fields': basefields}, {'id': 'download', 'legend': 'Token download data', 'fields': ['overview_name', 'overview_value', 'include_in_data']}, - {'id': 'marketing', 'legend': 'Marketing', 'fields': ['tweet_template', ]}, + {'id': 'marketing', 'legend': 'Marketing', 'fields': ['tweet_template', 'available_fields', ]}, {'id': 'params', 'legend': 'Parameters', 'fields': self.class_param_fields}, ] @@ -138,7 +141,7 @@ class BackendSponsorshipLevelBenefitForm(BackendForm): class Meta: model = SponsorshipBenefit fields = ['benefitname', 'benefitdescription', 'sortkey', 'maxclaims', - 'claimprompt', 'deadline', 'tweet_template', 'benefit_class_name', 'autoconfirm', + 'claimprompt', 'deadline', 'tweet_template', 'available_fields', 'benefit_class_name', 'autoconfirm', 'overview_name', 'overview_value', 'include_in_data', ] _can_multiclaim = None @@ -193,6 +196,8 @@ class BackendSponsorshipLevelBenefitForm(BackendForm): ] self.fields['tweet_template'].widget = MonospaceTextarea() + self.fields['available_fields'].widget = SimpleTreeviewWidget(treedata=self.get_contextrefs()) + if not self.can_multiclaim: del self.fields['maxclaims'] self.update_protected_fields() @@ -221,6 +226,15 @@ class BackendSponsorshipLevelBenefitForm(BackendForm): return p return '' + @classmethod + def get_contextrefs(self): + return { + 'benefit': dict(get_all_available_attributes(SponsorshipBenefit)), + 'level': dict(get_all_available_attributes(SponsorshipLevel)), + 'conference': dict(get_all_available_attributes(Conference)), + 'sponsor': dict(get_all_available_attributes(Sponsor)), + } + class BackendSponsorshipLevelBenefitManager(object): title = 'Benefits' diff --git a/postgresqleu/confsponsor/models.py b/postgresqleu/confsponsor/models.py index 823cc616..510071b3 100644 --- a/postgresqleu/confsponsor/models.py +++ b/postgresqleu/confsponsor/models.py @@ -108,6 +108,11 @@ class SponsorshipBenefit(models.Model): include_in_data = models.BooleanField(null=False, default=True, verbose_name="Include in data", help_text='Include information about this benefit in sponsorship data from tokens') + _safe_attributes = [ + 'benefitname', 'sortkey', 'benefitdescription', 'claimprompt', 'maxclaims', 'deadline', + 'autoconfirm', 'benefit_class', 'class_parameters', + ] + def __str__(self): return self.benefitname -- 2.39.5