Wagtail Admin Page에서 panels을 Custom 할 수 있다. 

 

 from wagtail.admin.edit_handlers import (
    ObjectList,
    TabbedInterface
)
    
    
class HomePage(Page):
	...

    # promote_panels = []
    # settings_panels = []
    
    banner_panels = [
        MultiFieldPanel([
            FieldPanel("banner_title"),
            FieldPanel("banner_subtitle"),
            ImageChooserPanel("banner_image"),
            PageChooserPanel("banner_cta"),
        ], heading="Banner Options"),
    ]
    
    edit_handler = TabbedInterface(
        [
            ObjectList(content_panels, heading="Content"),
            ObjectList(banner_panels, heading="Banner Settings"),
            ObjectList(Page.promote_panels, heading="Promotional Stuff"),
            ObjectList(Page.settings_panels, heading="Setting Stuff"),
        ]
    )

edit_handler를 통해 overide가 가능하다. 

 

'Back-End > Wagtail, Django' 카테고리의 다른 글

Wagtail StreamField Options  (0) 2021.12.02
Wagtail Custom Page Properties  (0) 2021.12.02
Wagtail Tags  (0) 2021.12.01
Wagtail Ajax Template  (0) 2021.12.01
Wagtail Cache  (0) 2021.11.28

Wagtail에서는 태그 기능을 지원한다. 

훌륭한 인터페이스로 제공된 Tag기능을 사용해보자.

 

 

1. Tag 클래스 모델 만들기

from taggit.models import TaggedItemBase


class BlogPageTag(TaggedItemBase):
    content_object = ParentalKey(
        'BlogDetailPage',
        related_name="tagged_items",
        on_delete=models.CASCADE
    )

먼저 Tag 모델을 만들어주자. 태그 기능을 사용할 class를 ParentalKey로 연결해주면 된다. 

 

 

2. tag 필드 만들기

from modelcluster.contrib.taggit import ClusterTaggableManager


class BlogDetailPage(Page):
    """Parental Blog Detail Page"""
	
    ...
    
    tags = ClusterTaggableManager(through=BlogPageTag, blank=True)

ParentalKey로 연결해준 클래스 모델에 tags라는 이름의 필드를 만든다. 

 

 

3. Content_Panels에 등록

content_panels = Page.content_panels + [
      	...
        FieldPanel("tags"),
]

content_panel에 tag를 등록하고 사용해준다.

 

 

4. tag로 검색

    def get_context(self, request, *args, **kwargs):
        context = super().get_context(request, *args, **kwargs)
        all_posts = BlogDetailPage.objects.live().public().order_by('-first_published_at')
        
        if request.GET.get('tag', None):
            tags= request.GET.get('tag')
        all_posts = all_posts.filter(tags__slug__in=[tags])

BlogListingPage에서 태그로 검색하는 기능을 만들고 싶다면 위와 같이 하면 된다. 

 

?tags=태그

 

 

5. Template

    <h1>Tags:</h1>

    {% for tag in page.tags.all %}
        <a href="/blog/?tag={{ tag.slug }}">{{ tag }} -- {{ tag.slug }}</a><br />
    {% endfor %}

page의 tags필드의 all로 모든 태그를 가져올 수 있다. 

 

 

'Back-End > Wagtail, Django' 카테고리의 다른 글

Wagtail Custom Page Properties  (0) 2021.12.02
Wagtail Custom Admin Tabs  (0) 2021.12.01
Wagtail Ajax Template  (0) 2021.12.01
Wagtail Cache  (0) 2021.11.28
Wagtail Recaptcha  (0) 2021.11.28

Wagtail Ajax Template을 간단하게 적어보고 넘어가려고 한다. 

 

 

1. base.html

{# Global javascript #}
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
-> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.js" integrity="sha512-WBbdKQKeIQFarq1hrOxNL/gnp0Tqh25fn0z3X1po+ej8iuHhHdp6Sh9l+tghGw5L1bsvtzjeuSKsL80RW3XdYw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

base.html에는 기본적으로 jquery slim버전이 있을 것이다. 하지만 slim은 ajax를 지원하지 않으니 https://cdnjs.com/libraries/jquery

으로 가서 ajax가 포함된 jquery로 바꿔주자.

 

 

2. blog/models.py

class BlogListingPage(RoutablePageMixin, Page):

    template = "blog/blog_listing_page.html"
    ajax_template = "blog/blog_listing_page_ajax.html"
    max_count = 1
    subpage_types = ['blog.ArticleBlogPage', 'blog.VideoBlogPage']

Wagtail은 ajax_template 기능을 제공한다. 새로운 html 파일을 만들어서 ajax 기능을 적으면 된다. 

 

 

3. Template blog/blog_listing_page_ajax.html

{% for post in posts %}
    <h1>{{ post.title }}</h1>
    {% if post.specific.subtitle %}
        <p>{{ post.specific.subtitle }}</p>
    {% endif %}
{% endfor %}

간단하게 post들의 title과 subtitle을 가져오는 템플릿을 작성하였다. 

 

 

4. 사용

크롬에서 f12를 누르고 개발자 도구에서 콘솔로 실행시킨다. 

 

 

'Back-End > Wagtail, Django' 카테고리의 다른 글

Wagtail Custom Admin Tabs  (0) 2021.12.01
Wagtail Tags  (0) 2021.12.01
Wagtail Cache  (0) 2021.11.28
Wagtail Recaptcha  (0) 2021.11.28
Wagtail Rich Editor Extend  (0) 2021.11.27

Cache에 대해서 알아보자.

 

웹 캐시(영어: web cache) 또는 HTTP 캐시(HTTP cache)는 서버 지연을 줄이기 위해 웹 페이지, 이미지, 기타 유형의 웹 멀티미디어 등의 웹 문서들을 임시 저장하기 위한 정보기술이다. 웹 캐시 시스템은 이를 통과하는 문서들의 사본을 저장하며 이후 요청들은 특정 조건을 충족하는 경우 캐시화가 가능하다.[1] 웹 캐시 시스템은 일종의 어플라이언스나 컴퓨터 프로그램을 의미할 수 있다. 동일한 서버에 다시 접근할 때에는 근처에 있는 프록시 서버의 웹 캐시에 저장된 정보를 불러오므로 더 빠른 열람이 가능하다.

 

출처: https://ko.wikipedia.org/wiki/%EC%9B%B9_%EC%BA%90%EC%8B%9C

 

소규모 사이트에는 굳이 필요 없을 수 있겠으나 사이트의 규모가 커지면 캐시를 적용하는 것을 고려해야한다. (사이트의 응답속도에 큰 차이가 있기 때문이다.)

 

 

1. Settings/dev.py 수정

...

CACHES = {
    "default": {
        "BACKEND": "django.core.cache.backends.filebased.FileBasedCache",
        "LOCATION": "wagtail project 폴더의 경로"
    }
}

...

참고로 경로를 복사하면 User\mycomputer\desktop.. 이런 형식으로 되어 있을텐데 \을 /로 경로 수정해줘야한다. 

경로는 cache가 저장될 위치를 의미하는데 원하는 경로가 있으면 수정해주면 된다. 

 

 

2. Templates 사용

 

blog/blog_listing_page.html

{% load cache %}

<div class="container">
        {% for post in posts %}
            {% cache 604800 blog_post_preview post.id %}
                <div class="row mt-5 mb-5">
                    <div class="col-sm-3">
                        {% image post.banner_image fill-250x250 as blog_img %}
                        <a href="{{ post.url }}">
                            <img src="{{ blog_img.url }}" alt="{{ blog_img.alt }}">
                        </a>
                    </div>
                    <div class="col-sm-9">
                            <h2>{{ post.custom_title }}</h2>
                            {% if post.specific.subtitle %}
                                <p>{{ post.specific.subtitle }}</p>
                            {% endif %}
                            <a href="{{ post.url }}" class="btn btn-primary mt-4">{{ post.title }}</a>
                        </a>
                    </div>
                </div>
                <br>
            {% endcache %}
        {% endfor %}
</div>

604800은 초를 의미하는데 604800초는 1주일을 의미한다. 캐시의 유지 기한이다. 설정을 해놓지 않으면 영원히 캐시가 유지된다. 그리고 blog_post_preview는 캐시 조각의 이름을 정해준 것이다. 마지막 post.id 각각의 post에 고유의 cache 아이디를 부여해준 것이다. 

 

주의)

이미 캐싱 되어 있는 데이터에 추가적인 정보를 넣게 되면 나타나지 않는다. 캐싱 되어 있어 그저 기존의 정보를 던져주기 때문이다. 그럴 때에는 직접 캐시 파일들을 삭제하거나 

from django.core.cache import cache
cache.clear()

Django shell을 열어서 위 명령어를 실행시켜주면 된다. 

 

 

추가)

 

다만 일부 정보만 주기적으로 업데이트 되고 나머지는 그렇지 않다면 모든 캐시를 삭제하는 방법은 비효율적이다. 이럴경우 필요한 곳에서만 캐쉬를 삭제하고 업데이트 해주는 방법이 맞다고 볼 수 있다. 

 

from django.core.cache import cache
from django.core.cache.utils import make_template_fragment_key


class BlogDetailPage(Page):

	....

  def save(self, *args, **kwargs):
    key = make_template_fragment_key("blog_post_preview", [self.id])
    cache.delete(key)
    return super().save(*args, **kwargs)

블로그 상세 페이지가 자주 업데이트 된다고 가정한다면 블로그 상세 페이지가 새로 save될 때마다 실행하는 save Magic Method를 만든다. 

 

key = make_template_fragment_key(something)는 something이라는 캐시를 템플릿에서 찾아서 key라는 변수에 저장한다. 그리고 cache.delete(key)를 사용하여 지우고 리턴해준다. 

'Back-End > Wagtail, Django' 카테고리의 다른 글

Wagtail Tags  (0) 2021.12.01
Wagtail Ajax Template  (0) 2021.12.01
Wagtail Recaptcha  (0) 2021.11.28
Wagtail Rich Editor Extend  (0) 2021.11.27
Wagtail API v2 Serializing Rich Text  (0) 2021.11.25

매크로 공격 방지를 위한 Recaptcha 기술을 사용하는 방법에 대해서 알아보자

 

Google Recaptcha를 사용한다. 

 

https://github.com/springload/wagtail-django-recaptcha

 

1. Google Recaptcha 접속

 

https://www.google.com/recaptcha/about/

 

 

새로 Recaptcha를 생성하고 사이트 Key와 비밀 Key를 따로 저장 해 놓는다. 

 

 

2. 모듈 설치

pip install django-wagtail-recaptcha

 

 

3. settings/base.py 수정

INSTALLED_APPS = [
	...
	'captcha',
      'wagtailcaptcha',
]

...

RECAPTCHA_PUBLIC_KEY = "사이트 KEY"
RECAPTCHA_PRIVATE_KEY = "비밀 KEY"
NOCAPTCHA = True

captcha는 2번에서 설치한 패키지 모듈이고 wagtailcaptcha는 captcha 모듈 기반의 wagtail captcha이다.

 

그리고 아까 Google Recaptcha에서 가져온 키를 넣는다. 

 

 

4. Models.py 수정

from wagtailcaptcha.models import WagtailCaptchaEmailForm


class ContactPage(WagtailCaptchaEmailForm): # AbstractEmailForm
    
    template = 'contact/contact_page.html'
    
    intro = RichTextField(blank=True)
    thank_you_text = RichTextField(blank=True)
    
    content_panels = AbstractEmailForm.content_panels + [
        FieldPanel('intro'),
        InlinePanel('form_fields', label="Form Fields"),
        FieldPanel('thank_you_text'),
        MultiFieldPanel([
            FieldRowPanel([
                FieldPanel('from_address', classname="col6"),
                FieldPanel('to_address', classname="col6")
            ]),
            FieldPanel("subject"),
        ], heading="Email Settings"),
    ]

기존에 AbstractEmailForm로 만들었던 Contact Page를 WagtailCaptchaEmailForm로 바꿔주자. 

 

'Back-End > Wagtail, Django' 카테고리의 다른 글

Wagtail Ajax Template  (0) 2021.12.01
Wagtail Cache  (0) 2021.11.28
Wagtail Rich Editor Extend  (0) 2021.11.27
Wagtail API v2 Serializing Rich Text  (0) 2021.11.25
Wagtail API v2 Serializing a QuerySet  (0) 2021.11.25

wagtail_hooks.py

import wagtail.admin.rich_text.editors.draftail.features as draftail_features
from wagtail.admin.rich_text.converters.html_to_contentstate import (
    InlineStyleElementHandler
)
from wagtail.core import hooks


@hooks.register("register_rich_text_features")
def register_code_styling(features):
    """Add the <code> to the richtext editor."""

    # Step 1
    feature_name = "code"
    type_ = "CODE"
    tag = "code"

    # Step 2
    control = {
        "type": type_,
        "label": "</>",
        "description": "Code"
    }

    # Step 3
    features.register_editor_plugin(
        "draftail", feature_name, draftail_features.InlineStyleFeature(control)
    )

    # Step 4
    db_conversion = {
        "from_database_format": {tag: InlineStyleElementHandler(type_)},
        "to_database_format": {"style_map": {type_: {"element": tag}}},
    }

    # Step 5
    features.register_converter_rule("contentstate", feature_name, db_conversion)

    # Step 6 optional
    # This will register this feature with all richtext editors by default
    features.default_features.append(feature_name)


@hooks.register("register_rich_text_features")
def register_centertext_feature(features):
    """Creates centered text in our richtext"""

    feature_name = "center"
    type_ = "CENTERTEXT"
    tag = "div"

    control = {
        "type": type_,
        "label": "Center", # 라벨
        "description": "Center Text", # 설명
        "style": { # css
            "display": "block",
            "text-align": "center",
        },
    }

    features.register_editor_plugin(
        "draftail", feature_name, draftail_features.InlineStyleFeature(control)
    )

    db_conversion = {
        "from_database_format": {tag: InlineStyleElementHandler(type_)},
        "to_database_format": {
            "style_map": {
                type_: {
                    "element": tag,
                    "props": {
                        "class": "d-block text-center",
                    }
                }
            }
        },
    }

    features.register_converter_rule("contentstate", feature_name, db_conversion)

    features.default_features.append(feature_name)

control의 style은 Admin Page에서 보이는 RichEditor, db_conversion의 props는 Front-end 단계의 Style

'Back-End > Wagtail, Django' 카테고리의 다른 글

Wagtail Cache  (0) 2021.11.28
Wagtail Recaptcha  (0) 2021.11.28
Wagtail API v2 Serializing Rich Text  (0) 2021.11.25
Wagtail API v2 Serializing a QuerySet  (0) 2021.11.25
Wagtail API v2 Custom Page Properties  (0) 2021.11.25

+ Recent posts