Skip to content

Instantly share code, notes, and snippets.

@LowerDeez
Last active November 21, 2017 08:53
Show Gist options
  • Save LowerDeez/07f1a4ab63bcf3139654bf7610cbd91c to your computer and use it in GitHub Desktop.
Save LowerDeez/07f1a4ab63bcf3139654bf7610cbd91c to your computer and use it in GitHub Desktop.
Django. Custom templates
from __future__ import unicode_literals
import logging
from django.utils.translation import ugettext_lazy as _
logger = logging.getLogger(__name__)
class TemplatesChoices:
ONE = 'layout/basic_template.jinja'
TWO = 'layout/basic_contact.jinja'
THREE = 'layout/basic_company_about.jinja'
FOUR = 'layout/basic_sertificate.jinja'
FIVE = 'layout/basic_documents.jinja'
CHOICES = [
(ONE, "Template with script block and banner block (Search tour and avia)."),
(TWO, 'Template with description, google maps script '
'and popup window to contact with administration (contacts).'),
(THREE, "Template with main image, inline images, and text block (About company page)."),
(FOUR, "Template with main image, text block "
"and button to contact with administration (Sertificate page)."),
(FIVE, "Template with tabs and two fields with html (Documents page).")
]
from django.contrib import admin
from django.shortcuts import redirect
from shared.admin.singltone_mixin import SingleObjectAdminModelMixin
from .models.page import TemplatePage
from .models.menu import Menu, MenuItem
from .models.singleton_social_links import SocialLinks
from .template_dict import template_fields
@admin.register(TemplatePage)
class TemplatePageAdmin(admin.ModelAdmin):
list_display = ['title', 'slug', 'link']
def get_fieldsets(self, request, obj=None):
if not obj:
fieldsets = (
(u'Basic fields', {
'fields': ('template', 'title')
}),
)
else:
fieldsets = template_fields[obj.template][0]
self.inlines = template_fields[obj.template][1]
return fieldsets
def response_add(self, request, obj, post_url_continue=None):
return redirect('/admin/basic/templatepage/{}/change'.format(obj.id))
class MenuItemInline(admin.TabularInline):
model = MenuItem
extra = 1
@admin.register(Menu)
class MenuAdmin(admin.ModelAdmin):
inlines = [MenuItemInline]
@admin.register(SocialLinks)
class SocialLinksModelAdmin(SingleObjectAdminModelMixin):
pass
include /../mixins/index
include mixins/blog__title.pug
+ext 'base.jinja'
+bl('head')
+exp super()
+bl('title')
title
+exp object.title
+bl('body')
+bl('documents')
.documents
.wrapper-inner
.blog__title
+exp object.sub_title
.documents__wrap
.documents__content
.documents__type
+for('tab in object.tabs.all()')
+if('loop.index == 1')
a.documents__button.documents__active(onclick="openTab(event,'" +exp('tab.slug') + "')")
+exp tab.name
+else
a.documents__button(onclick="openTab(event,'" +exp('tab.slug') + "')")
+exp tab.name
+for('tab in object.tabs.all()')
+if('loop.index == 1')
//- standart html
.html_standart(id=exp('tab.slug'))
+exp df.safe(tab.html)
//-for mobile version
.html_for_mobile(id=exp('tab.slug') + '-mobile')
+exp df.safe(tab.html_mobile)
+else
//- standart html
.html_standart(id=exp('tab.slug'), style={'display': 'none'})
+exp df.safe(tab.html)
//- for mobile version
.html_for_mobile(id=exp('tab.slug') + '-mobile', style={'display': 'none'})
+exp df.safe(tab.html_mobile)
script(type="text/javascript").
function openTab(evt, tabName) {
var i, tablinks;
//- for standart tabs
var x = document.getElementsByClassName("html_standart");
for (i = 0; i < x.length; i++)
{
x[i].style.display = "none";
}
document.getElementById(tabName).style.display = "block";
//- for mobile
var x = document.getElementsByClassName("html_for_mobile");
for (i = 0; i < x.length; i++)
{
x[i].style.display = "none";
}
document.getElementById(tabName + '-mobile').style.display = "block";
//- change active class for tablinks
tablinks = document.getElementsByClassName("documents__button");
for (i = 0; i < x.length; i++) {
tablinks[i].className = tablinks[i].className.replace(" documents__active", "");
}
evt.currentTarget.className += " documents__active";
}
include /../mixins/index
+ext 'base.jinja'
+bl('head')
+exp super()
+bl('title')
title
+exp object.title
+bl('css')
+exp super()
link(rel="stylesheet", type="text/css", href!=static_s("css/search.css"))
+bl('body')
+bl('static_content')
.search-tour.avia(style={background: 'url(' + exp("object.bg_image") + ')' + ' no-repeat'})
.wrapper-inner
.tour__name
+exp object.title
.search-tour__content
.search-tour__part.clearfix
//- left side
.search-tour__block
.search-tour__modul
+exp df.safe(object.script)
//- right side
.search-tour__banner
a.search-tour__link(href="#", style={background: 'url(' + exp("object.image") + ')'})
.search-tour__button
+trans Подробнее
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.utils.text import slugify
from stem.core.models.base import BaseModel
from stem.core.models.orderable import OrderableModel
from apps.sliders.models.abstract_slider import AbstractSlider
from shared.storages.storage import OverwriteStorage
from ckeditor.fields import RichTextField
from unidecode import unidecode
from . import TemplatesChoices
class TemplatePage(BaseModel):
"""
Template Page Model
Attributes:
template: path to template
link: link to object of the model
title: page title
slug: page slug for link
script: field for some external script
banner_image: image
button_link: link for banner image
text_field: text
"""
template = models.CharField(
_("Файл шаблона"),
choices=TemplatesChoices.CHOICES,
max_length=250,
blank=True, null=True
)
link = models.CharField(
_("Ссылка"),
max_length=256,
blank=True, null=True,
help_text=_("Используйте эту ссылку для пунктов меню."),
)
title = models.CharField(
_("Заголовок"),
max_length=120,
unique=True
)
slug = models.SlugField(
max_length=120,
blank=True, null=True,
unique=True,
db_index=True
)
# common field
script = models.TextField(
_("Скрипт или фрейм (например, для Google Maps)"),
blank=True, null=True
)
background_image = models.ImageField(
_("Картинка фона"),
upload_to='templates/background/',
storage=OverwriteStorage(),
blank=True, null=True
)
# first template fields
banner_image = models.ImageField(
_("Картинка в шаблоне"),
upload_to='templates/banners/',
storage=OverwriteStorage(),
blank=True, null=True
)
button_link = models.CharField(
_("Ссылка кнопки"),
max_length=256,
blank=True, null=True,
help_text=_("Путь должен начинаться с '/', если это внутрення ссылка.")
)
# second template fields
text_field_title = models.CharField(
_("Заголовок для текстового поля"),
max_length=150,
blank=True, null=True
)
text_field = RichTextField(
_("Текстовое поле"),
blank=True, null=True
)
# fifth template fields
sub_title = models.CharField(
_("Подзаголовок"),
max_length=256,
blank=True, null=True,
)
class Meta:
verbose_name = _("Страница с шаблоном")
verbose_name_plural = _("Страницы с шаблоном")
def __str__(self):
return self.title
@property
def bg_image(self):
if self.background_image:
return self.background_image.url
else:
return None
@property
def image(self):
if self.banner_image:
return self.banner_image.url
else:
return None
def save(self, *args, **kwargs):
if not self.id:
self.slug = slugify(unidecode(self.title))
self.link = '/basic/{}/'.format(self.slug)
return super().save(*args, **kwargs)
class TemplateSlider(AbstractSlider):
page = models.ForeignKey(
TemplatePage,
verbose_name="Страница",
related_name='sliders'
)
title = models.CharField(
_("Заголовок"),
max_length=250,
blank=True, null=True
)
description = models.TextField(
_("Описание"),
blank=True, null=True
)
def __str__(self):
return "Слайдер"
class TabsWithHtml(OrderableModel):
page = models.ForeignKey(
TemplatePage,
verbose_name="Страница",
related_name='tabs'
)
name = models.CharField(
_("Имя вкладки"),
max_length=50
)
slug = models.SlugField(
max_length=50,
blank=True, null=True,
db_index=True
)
html = RichTextField(
_("HTML")
)
html_mobile = RichTextField(
_("HTML for mobile")
)
class Meta:
verbose_name = _("Вкладка")
verbose_name_plural = _("Вкладки")
ordering = ['order']
def __str__(self):
return self.name
def save(self, *args, **kwargs):
if not self.id:
self.slug = slugify(unidecode(self.name))
return super().save(*args, **kwargs)
from django.contrib import admin
from stem.core.admin.inlines import FlowInline
from .models.page import TemplateSlider, TabsWithHtml
from .models import TemplatesChoices
class TabInline(FlowInline):
model = TabsWithHtml
extra = 0
prepopulated_fields = {"slug": ("name",)}
class TemplateSliderInline(admin.StackedInline):
model = TemplateSlider
extra = 0
template_fields = \
{
TemplatesChoices.ONE:
[
(
(u'Template specific fields', {
'fields': ('slug', 'background_image', 'script', 'banner_image', 'button_link')
}),
),
[]
],
TemplatesChoices.TWO:
[
(
(u'Template specific fields', {
'fields': ('slug', 'background_image', 'script', 'text_field')
}),
),
[]
],
TemplatesChoices.THREE:
[
(
(u'Template specific fields', {
'fields': ('slug', 'background_image', 'banner_image', 'text_field_title', 'text_field')
}),
),
[TemplateSliderInline]
],
TemplatesChoices.FOUR:
[
(
(u'Template specific fields', {
'fields': ('slug', 'background_image', 'banner_image', 'text_field_title', 'text_field')
}),
),
[]
],
TemplatesChoices.FIVE:
[
(
(u'Template specific fields', {
'fields': ('slug', 'sub_title')
}),
),
[TabInline]
]
}
from django.conf import settings
from django.core.cache.backends.base import DEFAULT_TIMEOUT
from django.views.decorators.cache import cache_page
from stem.core.views.base import TemplateView, DetailView, SLUG_REGEX
from .models.page import TemplatePage
CACHE_TTL = getattr(settings, 'CACHE_TTL', DEFAULT_TIMEOUT)
class CustomTemplateView(DetailView):
name = 'basic-template'
url_regex_list = [SLUG_REGEX]
url_prefix = ''
queryset = TemplatePage.objects.only('link', 'title').prefetch_related('tabs')
cache_timeout = CACHE_TTL
def get_cache_timeout(self):
return self.cache_timeout
def dispatch(self, *args, **kwargs):
return cache_page(self.get_cache_timeout())(super().dispatch)(*args, **kwargs)
def get_template_names(self):
return [self.object.template]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment