Skip to content

Instantly share code, notes, and snippets.

@pyzenberg
Created August 3, 2024 17:24
Show Gist options
  • Save pyzenberg/71bc538cfa7ffe19458073c65f36fe29 to your computer and use it in GitHub Desktop.
Save pyzenberg/71bc538cfa7ffe19458073c65f36fe29 to your computer and use it in GitHub Desktop.
Wagtail 4.2 localized settings. So site can have different settings for their language. For example two twitter account each for a language.
from django.conf import settings
from django.db import models
from django.forms import Textarea
from django.urls import reverse
from django.utils.functional import cached_property
from django.utils.translation import gettext as _, get_language
from modelcluster.fields import ParentalKey
from modelcluster.models import ClusterableModel
from wagtail.admin.panels import FieldPanel, MultiFieldPanel, TabbedInterface, InlinePanel, ObjectList
from wagtail.contrib.settings.models import BaseGenericSetting
from wagtail.contrib.settings.registry import register_setting
from wagtail.fields import RichTextField
from wagtail.images import get_image_model_string
from wagtail.models import Orderable
from wagtailgeowidget.helpers import geosgeometry_str_to_struct
from wagtailgeowidget.panels import LeafletPanel
@register_setting
class LocalizedConfig(BaseGenericSetting, ClusterableModel):
language_code = models.CharField(
_('زبان'),
max_length=2,
unique=True,
)
# social network tab
twitter = models.URLField(_('توییتر'), blank=True)
youtube = models.URLField(_('یوتیوب'), blank=True)
instagram = models.URLField(_('اینستاگرام'), blank=True)
linkedin = models.URLField(_('لینکدین'), blank=True)
telegram = models.URLField(_('تلگرام'), blank=True)
whatsapp = models.URLField(_('واتساپ'), blank=True)
facebook = models.URLField(_('فیسبوک'), blank=True)
_tab_socials = [
FieldPanel('twitter'),
FieldPanel('instagram'),
FieldPanel('youtube'),
FieldPanel('linkedin'),
FieldPanel('telegram'),
FieldPanel('whatsapp'),
FieldPanel('facebook'),
]
# contact tab
phone = models.CharField(_('تلفن'), max_length=255, blank=True)
email = models.EmailField(_('ایمیل'), blank=True)
address = models.CharField(_('نشانی'), max_length=255, blank=True)
open_hours = models.CharField(_('ساعات کار'), max_length=255, blank=True)
location = models.CharField(_('لوکیشن'), max_length=255, blank=True)
location_title = models.CharField(_('عنوان لوکیشن'), default=_('دفتر مرکزی'), max_length=255, blank=True)
_tab_contacts = [
FieldPanel('phone'),
FieldPanel('email'),
FieldPanel('address', widget=Textarea(attrs={'rows': 2})),
FieldPanel('open_hours'),
LeafletPanel('location'),
FieldPanel('location_title'),
]
# header
default_keywords = models.CharField(
_('کلمات کلیدی پیش فرض'),
max_length=255,
blank=True,
)
main_menu_align = models.CharField(
_('چینش منوی اصلی'),
max_length=8,
choices=(
('center', _('وسط')),
('start', _('شروع خط')),
('end', _('پایان خط')),
),
default='center',
)
breadcrumb_bg = models.ForeignKey(
verbose_name=_('تصویر زمینه پیش فرض'),
to=get_image_model_string(),
on_delete=models.SET_NULL,
related_name='+',
help_text='1920x331',
blank=True,
null=True,
)
header_box_title = models.CharField(
_('عنوان کناری'),
max_length=128,
default=_('آیا نیاز به مشاوره دارید؟'),
blank=True,
help_text=_('در کادر کناری پست های بلاگ نمایش داده می‌شود'),
)
header_box_desc = models.CharField(
_('متن کناری'),
max_length=512,
default=_(
'کارشناسان ما در طول هفته منتظر تماس شما جهت دادن مشاوره هستند.'
'برای جزییات بیشتر روی کلید پایین کلیک کنید'
),
blank=True,
help_text=_('در کادر کناری پست های بلاگ نمایش داده می‌شود'),
)
header_button_title = models.CharField(
_('عنوان کلید هدر'),
max_length=32,
blank=True,
help_text=_('اگر وارد شود جایگزین عنوان صفحه مقصد می‌شود'),
)
header_button_page = models.ForeignKey(
to='wagtailcore.Page',
on_delete=models.SET_NULL,
blank=True,
null=True,
verbose_name=_('صفحه مقصد'),
)
header_button_url = models.URLField(
_('نشانی کلید هدر'),
help_text=_('در صورتی که میخواهید به یک URL خاص خارج از وب سایت هدایت کنید'),
blank=True,
)
header_button_pattern = models.CharField(
_('الگوی نشانی'),
max_length=64,
blank=True,
help_text=_('ارسال به یک الگوی نشانی داخلی ثبت شده'),
)
_tab_header = [
FieldPanel('default_keywords'),
FieldPanel('main_menu_align'),
FieldPanel('breadcrumb_bg'),
FieldPanel('header_box_title'),
FieldPanel('header_box_desc', widget=Textarea(attrs={'rows': 2})),
FieldPanel('header_button_title'),
FieldPanel('header_button_page'),
FieldPanel('header_button_url'),
FieldPanel('header_button_pattern'),
]
# branding tab
name_short = models.CharField(_('نام کوتاه'), max_length=16, blank=True)
name_full = models.CharField(_('نام کامل'), max_length=64, blank=True)
seo_desc = models.CharField(_('شرح سئو'), max_length=255, blank=True)
icon_dark = models.ForeignKey(
verbose_name=_('آیکن تیره'),
to=get_image_model_string(),
on_delete=models.SET_NULL,
related_name='+',
help_text=_('با فورمت و بدون زمینه') + ' 255x255',
blank=True,
null=True,
)
icon_light = models.ForeignKey(
verbose_name=_('آیکن روشن'),
to=get_image_model_string(),
on_delete=models.SET_NULL,
related_name='+',
help_text=_('با فورمت و بدون زمینه') + ' 255x255',
blank=True,
null=True,
)
logo_dark = models.ForeignKey(
verbose_name=_('تصویر لوگو تیره'),
to=get_image_model_string(),
on_delete=models.SET_NULL,
related_name='+',
help_text=_('با فورمت و بدون زمینه') + ' 188x32',
blank=True,
null=True,
)
logo_light = models.ForeignKey(
verbose_name=_('تصویر لوگو روشن'),
to=get_image_model_string(),
on_delete=models.SET_NULL,
related_name='+',
help_text=_('با فورمت و بدون زمینه') + ' 188x32',
blank=True,
null=True,
)
_tab_branding = [
FieldPanel('name_short'),
FieldPanel('name_full'),
FieldPanel('seo_desc'),
FieldPanel('icon_dark'),
FieldPanel('icon_light'),
FieldPanel('logo_dark'),
FieldPanel('logo_light'),
]
# footer
copyright = models.CharField(
_('کپی رایت'),
max_length=255,
default=_('متن کپی رایت'),
)
footer_desc = models.TextField(
_('شرح فوتر'),
max_length=512,
default=_('شرح فوتر در این بخش نوشته می‌شود.'),
)
footer_link_col_one_title = models.CharField(
_('عنوان ستون اول'),
default=_('عنوان ستون اول'),
max_length=64,
blank=True,
)
footer_link_col_two_title = models.CharField(
_('عنوان ستون دوم'),
default=_('عنوان ستون دوم'),
max_length=64,
blank=True,
)
_tab_footer = [
FieldPanel('copyright'),
FieldPanel('footer_desc', widget=Textarea(attrs={'rows': 2})),
ObjectList([
FieldPanel('footer_link_col_one_title'),
InlinePanel('footer_link_col_one', heading=_('ستون اول لینک ها'), label=_('لینک')),
], heading=_('ستون اول')),
ObjectList([
FieldPanel('footer_link_col_two_title'),
InlinePanel('footer_link_col_two', heading=_('ستون دوم لینک ها'), label=_('لینک')),
], heading=_('ستون دوم')),
]
# dashboard settings
kyc_content = RichTextField(
_('متن کادر اطلاعات شخصی (KYC)'),
default=_('[متن این کادر را از پنل مدیریت محتوا بخش «پیکربندی وب سایت و داشبورد» تغییر دهید]'),
blank=True,
)
loc_content = RichTextField(
_('متن کادر تعهدنامه'),
default=_('[متن این کادر را از پنل مدیریت محتوا بخش «پیکربندی وب سایت و داشبورد» تغییر دهید]'),
blank=True,
)
investment_indirect_landing_page = models.ForeignKey(
to='wagtailcore.Page',
on_delete=models.SET_NULL,
related_name='+',
blank=True,
null=True,
verbose_name=_('لندینگ سرمایه گذاری غیرمستقیم'),
)
_tab_dashboard = [
FieldPanel('kyc_content'),
FieldPanel('loc_content'),
FieldPanel('investment_indirect_landing_page'),
]
panels = [
TabbedInterface([
MultiFieldPanel(_tab_branding, heading=_('برندینگ')),
MultiFieldPanel(_tab_socials, heading=_('شبکه های اجتماعی')),
MultiFieldPanel(_tab_contacts, heading=_('تماس')),
MultiFieldPanel(_tab_header, heading=_('هدر')),
MultiFieldPanel(_tab_footer, heading=_('فوتر')),
MultiFieldPanel(_tab_dashboard, heading=_('داشبورد')),
]),
]
class Meta:
verbose_name = _('پیکربندی وب سایت و داشبورد')
def save(self, *args, **kwargs):
if not self.language_code:
self.language_code = get_language() or settings.LANGUAGE_CODE
super().save(*args, **kwargs)
@classmethod
def base_queryset(cls):
queryset = cls.objects.filter(language_code=get_language())
if cls.select_related is not None:
queryset = queryset.select_related(*cls.select_related)
return queryset
def get_header_button_link(self):
if self.header_button_page:
return self.header_button_page.url
elif self.header_button_url:
return self.header_button_url
elif self.header_button_pattern:
return reverse(self.header_button_pattern)
return '#'
def get_header_button_title(self):
if self.header_button_title:
return self.header_button_title
elif self.header_button_page:
return self.header_button_page.title
@cached_property
def location_point(self):
return geosgeometry_str_to_struct(self.location)
@property
def location_lat(self):
return self.location_point['y']
@property
def location_lng(self):
return self.location_point['x']
@property
def get_default_keywords(self):
return self.default_keywords.replace('،', ',').strip()
class FooterLinkItem(models.Model):
page = models.ForeignKey(
to='wagtailcore.Page',
verbose_name=_('صفحه'),
on_delete=models.CASCADE,
blank=True,
null=True,
)
title = models.CharField(
_('عنوان'),
max_length=64,
help_text=_('اگر وارد شود و صفحه ای انتخاب شده باشد عنوان پیش فرض تغییر میکند.'),
blank=True,
)
url = models.URLField(
_('پیوند'),
help_text=_('در صورتی که به صفحه ای خارج از سایت لینک داده شود. حتما باید عنوان وارد شود'),
blank=True,
)
panels = [
FieldPanel('page'),
FieldPanel('title'),
FieldPanel('url'),
]
class Meta:
verbose_name = _('لینک فوتر')
verbose_name_plural = verbose_name
abstract = True
def __str__(self):
return self.get_title()
def get_title(self):
if self.title:
return self.title
elif self.page:
return self.page.title
return _('بدون عنوان')
def get_link(self):
if self.page:
return self.page.url
elif self.url:
return self.url
return '#'
class FooterLinkCol1(Orderable, FooterLinkItem):
col_one = ParentalKey(LocalizedConfig, on_delete=models.CASCADE, related_name='footer_link_col_one')
class FooterLinkCol2(Orderable, FooterLinkItem):
col_two = ParentalKey(LocalizedConfig, on_delete=models.CASCADE, related_name='footer_link_col_two')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment