Wagtail이나 Django로 개발을 하다보면 orm을 사용하게 된다. 

보통 shell을 많이 사용하는데 shell은 직접 사용 모듈을 import해야하는 번거로움이 있다. 

Django_extensions은 미리 관련 module을 import 해줘서 효율적인 개발을 도와준다. 

 

 

설치방법은 아래와 같다. 

pip install django-extensions

 

settings/dev.py

INSTALLED_APPS = INSTALLED_APPS + [
    'django_extensions',
]

 

 

설치를 다 했으면 실행시켜보자.

python manage.py shell_plus

 

몇가지 Wagtail과 Django에서 사용하는 orm을 정리해보려고 한다.

 

 

1) all()

BlogDetailPage.objects.all()

모든 BlogDetailPage의 객체들을 가져온다.

 

2) last()

BlogDetailPage.objects.last()

마지막에 작성된 BlogDetailPage의 객체를 가져온다.

 

3) first()

BlogDetailPage.objects.first()

첫번째로 작성된 BlogDetailPage의 객체를 가져온다.

 

4) live()

BlogDetailPage.objects.live()

현재 발행 중인(wagtail) 객체를 가져온다.

 

5) filter()

BlogDetailPage.objects.filter(title="Blog Post #1")

특정 조건의 객체를 가져온다.

 

6) list

posts = BlogDetailPage.objects.all()
first_post = posts[0]

첫번째 순서에 위치 되어 있는 객체를 가져온다.

 

7) __dict__

first_post.__dict__

객체의 모든 정보를 가져온다.

 

8) __dir__

first_post.__dir__

객체가 저장되어 있는 메모리 주소를 가져온다.

 

9) get_parent()

first_post.get_parent()

객체의 부모 페이지 객체를 가져온다.

 

10) siblings()

first_post.get_siblings()

같은 레벨의 객체들을 가져온다.

 

11) save()

first_post.title = "First Blog Post (test title)"
first_post.save()
first_post
>><BlogDetailPage: First Blog Post (test title)>

객체의 변경내용을 저장한다.

 

 

추가)

하지만 django_extensions보다 더욱 편리하게 사용할 수 있는 방법이 있다. 

 

1. ipython 설치

pip install ipython

 

2. ipython 실행

python manage.py shell_plus --ipython

 

3. using TAB

객체를 입력하고 tab key를 누르면 모든 orm이 나온다. 물론 전부 사용할 수 있는 것이 아니라 객체의 정상적인 orm을 사용해야할 것이다. 

 

종료하고 싶을 때는 

exit

 

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

Django Request, Requests  (0) 2021.12.16
Django Signals  (0) 2021.10.22
Django ORM  (0) 2021.10.21
Django iamport 적용하기  (0) 2021.10.06
Django Bulma 적용 방법  (0) 2021.08.24
class ButtonBlock(blocks.StructBlock):
      button_page = blocks.PageChooserBlock(required=False)
      button_url = blocks.URLBlock(required=False)

여기 StructBlock에 2개의 Field Block이 있다. 이걸로 a태그로 만들어 관련 페이지로 이동하게 하는 기능을 만들고 싶어한다고 가정해보자. 내부 Link로 이동하고 싶으면 button_page를 외부 링크로 이동하고 싶으면 button_url을 사용한다. (이동하는 url은 한개이기 때문에 Field Block 한개만 사용한다. )

 

 

이럴경우 보통 Template에서

{% if card.button_page %}
  <a href="{{ card.button_page.url }}" class="btn btn-primary">
  	Learn More (internal)
	</a>
{% elif card.button_url %}
  <a href="{{ card.button_url }}" class="btn btn-primary">
  	Learn More (external)
  </a>
{% endif %}

위와 같이 사용한다. 물론 잘못된 것이 아니다. 하지만 2개의 Field Block말고 수많은 Field Block중 한가지만 사용하고 싶을 때에는 아마도 elif가 끊임 없이 늘어나서 Template이 지저분해질 것이다. (신경 안쓰인다면 뒤로가기 버튼을 누르면 된다.)

 

그래서 If Logic을 미리 BackEnd에서 처리하는 방법을 알아보려고 한다.

 

 

class LinkStructValue(blocks.StructValue):
    """Additional logic for our urls."""
    
    def url(self):
        button_page = self.get('button_page')
        button_url = self.get('button_url')
        if button_page:
            return button_page.url
        elif button_url:
            return button_url
        
        return None

방법은 간단하다. StructValue를 상속받은 LinkStructValue를 만들어주었다. (StructBlock이 아니다.) 

그리고 여기서 관련 Logic을 작성해주면 된다.

 

이후 간단하게 ButtonBlock에

class ButtonBlock(blocks.StructBlock):
    """An external or internal URL."""
    
    button_page = blocks.PageChooserBlock(required=False, help_text="If selected, this url will be used first")
    button_url = blocks.URLBlock(required=False, help_text="If added, this url will be used secondarily to the button page")
       
    class Meta:
        template = "streams/button_block.html"
        icon = "placeholder"
        label = "Single Button"
        value_class = LinkStructValue

value_class를 등록해주면 된다. 

자, 이제 이렇게 되면 BackEnd 단계에서 Logic을 처리하고 FrontEnd의 템플릿은 깔끔해질 것이다. 

 

심지어

class LinkStructValue(blocks.StructValue):
    """Additional logic for our urls."""
    
    def url(self):
        button_page = self.get('button_page')
        button_url = self.get('button_url')
        if button_page:
            return button_page.url
        elif button_url:
            return button_url
        
        return None
    
    def latest_posts(self):
        return BlogDetailPage.objects.live().public()[:3]

위와 같이 다른 객체를 가져와서 return해주는 것도 가능하다. 

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

Wagtail Menu System  (0) 2021.11.23
Wagtail, Django Paginator  (0) 2021.11.21
Wagtail Sitemap  (0) 2021.11.17
Wagtail 참고 사이트  (0) 2021.11.17
Wagtail git ignore setting  (0) 2021.11.16

사이트맵은 사용자나 소프트웨어를 통해 접근이 가능하다. 수많은 사이트들은 체계적인 뷰, 일반적으로 사이트의 계층적인 뷰를 표출하기 위해 사용자가 볼 수 있는 사이트맵을 보유하고 있다. 방문자가 특정 문서를 찾는데 도움을 주고 웹 크롤러에 의해 사용될 수도 있다.

검색 엔진과 기타 크롤러가 사용하는 경우 사이트 내 문서를 나열하는 XML 사이트맵이라는 구조화된 포맷이 있어서 상대적 중됴오와 업데이트 주기를 알 수 있다. 이는 robots.txt 파일로부터 지시되며 보통 sitemap.xml이라는 이름을 가진다.

한 번에 사이트 개요 내용을 볼 수 있도록 둘러보기 도움을 제공하는 역할을 하기도 한다.

 

https://ko.wikipedia.org/wiki/%EC%82%AC%EC%9D%B4%ED%8A%B8%EB%A7%B5

 

사이트맵 - 위키백과, 우리 모두의 백과사전

구글이 정의한 XML 사이트맵 파일 프로토콜에 대해서는 사이트맵스 문서를 참고하십시오. 사이트맵(sitemap) 또는 사이트 맵(site map)은 도메인 내의 웹사이트의 페이지 목록이다. 사이트 맵에는 3가

ko.wikipedia.org

 

1. Settings/base.py

INSTALLED_APPS = [
	...
	'wagtail.contrib.sitemaps',
    	...
    	'django.contrib.sitemaps'
]

 

 

2. myproject/urls.py

...
from wagtail.contrib.sitemaps.views import sitemap
...


urlpatterns = [
	...
    path('sitemap.xml', sitemap),

]

http://127.0.0.1:8000/sitemaps.xml

 

 

 

 

3. models.py

class BlogListingPage(RoutablePageMixin, Page):
    
    template = "blog/blog_listing_page.html"
    
    custom_title = models.CharField(
        max_length=100, 
        blank=False,
        null=False,
        help_text="Overwrites the default title",
        )
    
    content_panels = Page.content_panels + [
        FieldPanel("custom_title"),
    ]

    def get_context(self, request, *args, **kwargs):
        context = super().get_context(request, *args, **kwargs)
        context['posts'] = BlogDetailPage.objects.live().public()         
        return context
    
    @route(r'^latest/$')
    def latest_blog_posts(self, request, *args, **kwargs):
        context = self.get_context(request, *args, **kwargs)
        context["posts"] = context["posts"][:1]
        return render(request, "blog/latest_posts.html", context)
    
    def get_sitemap_urls(self, request):
        # 사이트 맵을 사용하고 싶지 않을때는 return [] 을 해주면 된다.
        
        sitemap = super().get_sitemap_urls(request)
        sitemap.append(
            {
                "location": self.full_url + self.reverse_subpage("latest_blog_posts"),
                "lastmod": (self.last_published_at or self.latest_revision_created_at),
                "priority": 0.9,
            }
        )
        
        return sitemap

get_sitemap_urls 함수를 확인하면 된다. 일반적으로 Publish된 Page 모델들은 Sitemap이 잘 나타나지만 latest_blog_posts처럼 templates으로 render할 경우 Sitemap에 표시되지 않는다. 그럴경우 get_sitemap_urls로 직접 정의 해주면 된다. 

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

Wagtail, Django Paginator  (0) 2021.11.21
Wagtail StructValue  (0) 2021.11.18
Wagtail 참고 사이트  (0) 2021.11.17
Wagtail git ignore setting  (0) 2021.11.16
Wagtail Routable Pages  (0) 2021.11.16

1. 공식 문서 사이트 : https://docs.wagtail.io/en/stable/

2. Awesome Wagtail : https://github.com/springload/awesome-wagta

3. awesomeonpensource : https://awesomeopensource.com/projects/wagtail

4. neon jungle : https://github.com/neon-jungle

5. django : https://github.com/django/django/tree/main

6. wagtail : https://github.com/wagtail/wagtail

7. 장고 공식 문서 사이트 : https://www.djangoproject.com/

8. Accord Box : https://www.accordbox.com/blog/wagtail-tutorials/

9. learn wagtail : https://learnwagtail.com/

-> https://github.com/CodingForEverybody/learn-wagtail

-> https://www.youtube.com/c/CodingForEverybody

10. bakerydemo : https://github.com/wagtail/bakerydemo

11. consumerfinance : https://cfpb.github.io/consumerfinance.gov/

12. third-party tutorials : https://docs.wagtail.io/en/stable/advanced_topics/third_party_tutorials.html#third-party-tutorials

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

Wagtail StructValue  (0) 2021.11.18
Wagtail Sitemap  (0) 2021.11.17
Wagtail git ignore setting  (0) 2021.11.16
Wagtail Routable Pages  (0) 2021.11.16
Wagtail BaseSetting  (0) 2021.11.15

.gitignore

__pycache__/
0*.py
!home/migrations/0001*
!home/migrations/0002*
media/

Wagtail로 프로젝트를 진행할 때, gitignore에 기본적으로 추가해주면 된다.

 

 

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

Wagtail Sitemap  (0) 2021.11.17
Wagtail 참고 사이트  (0) 2021.11.17
Wagtail Routable Pages  (0) 2021.11.16
Wagtail BaseSetting  (0) 2021.11.15
Wagtail Debug Toolbar(+ Django)  (0) 2021.11.13

https://www.youtube.com/watch?v=W2oHKiAYl3U&list=PLMQHMcNi6ocsS8Bfnuy_IDgJ4bHRRrvub&index=17 

 

Wagtail Routable Pages를 공부하면서 정리해보려고 한다. 

 

그동안 프로젝트를 진행하면서 Ajax 사용으로 많이 사용했었는데 정확한 사용방법을 숙지하지 못했던 것 같아서 정리하고 넘어가려고 한다. 

 

1. Settings

 

settings/base.py

INSTALLED_APPS = [
	'wagtail.contrib.routable_page',
]

 

 

 

2. Models

 

blog/models.py

from django.shortcuts import render
...
from wagtail.contrib.routable_page.models import RoutablePageMixin, route


class BlogListingPage(RoutablePageMixin, Page):
    
    template = "blog/blog_listing_page.html"
    
    custom_title = models.CharField(
        max_length=100, 
        blank=False,
        null=False,
        help_text="Overwrites the default title",
        )
    
    content_panels = Page.content_panels + [
        FieldPanel("custom_title"),
    ]

    def get_context(self, request, *args, **kwargs):
        context = super().get_context(request, *args, **kwargs)
        context['posts'] = BlogDetailPage.objects.live().public()         
        return context
    
    @route(r'^latest/$')
    def latest_blog_posts(self, request, *args, **kwargs):
        context = self.get_context(request, *args, **kwargs)
        context["posts"] = context["posts"][:1]
        return render(request, "blog/latest_posts.html", context)

동영상대로 BlogListPage에 추가했다. 여기서 중요한 점은 RoutablePageMixin을 Page앞에 적어줘야 한다는 점이다. 

(RoutablePageMixin, Page)

 

route를 사용하기 위해 데코레이터를 사용하는데 

@route(r'^$')형태로 사용한다. ^와$ 사이에 이동할 url 주소를 적어주면 된다.

(/는 Wagtail과 Django url 설정의 기본이다. 다만 ?를 사용할 경우 생략해도 되는데 ?가 자동으로 /를 추가해주기 때문이다. @route(r'^latest?$'))

 

route에서 get_context을 overwrite할 수가 있다. get_context에서는 현재 발행 중인 모든 blog post를 posts에 저장하여 return 해주었고 route에서는 context를 overwrite해서 가장 최근에 등록된 blog post 1개를 보여주는 것이다. 

 

그리고 blog/latest_posts.html에 request와 context를 같이 render 해준다.

 

 

3. Templates

 

2개의 template를 살펴볼 것이다. 한개는 blog_listing_page.html 다른 하나는 latest_posts.html이다. 

 

1)

blog/blog_listing_page.html

{% extends "base.html" %}

{% load wagtailimages_tags wagtailroutablepage_tags %}

{% block content %}

    <a href="{% routablepageurl page 'latest_blog_posts' %}">View Latest Posts Only</a>

    <div class="container">
        {% for post in posts %}
            <div class="row">
                <div class="col-sm-3">
                    {% image post.blog_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">
                    <a href="{{ post.url }}">
                        {{ post.custom_title }}
                    </a>
                </div>
            </div>
            <br>
        {% endfor %}
    </div>

{% endblock content %}

route를 연결해주기 위해 상단에 {% load wagtailroutablepage_tags %}을 적용하였다. 

a 태그를 누르면 route 페이지로 이동하려고 하는데 Django url이 아닌 Wagtail의 routable url를 사용한다. 

 

<a href="{% routablepageurl page 'latest_blog_posts' %}">View Latest Posts Only</a>

여기서 살펴볼 것은 route데코레이터가 붙은 함수명을 사용한다는 것이다. (함수명이 길 때에는 name을 사용하면 된다.

@route(r'^latest/$', name="route_name"))으로 적어주고 
 
<a href="{% routablepageurl page 'route_name' %}">View Latest Posts Only</a>

으로 사용한다.)

 

2)

blog/latest_posts.html

{% extends "base.html" %}

{% load wagtailimages_tags %}

{% block content %}

    <div class="container">
        <h1>Latest Posts </h1>
        {% for post in posts %}
            <div class="row">
                <div class="col-sm-3">
                    {% image post.blog_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">
                    <a href="{{ post.url }}">
                        {{ post.custom_title }}
                    </a>
                </div>
            </div>
            <br>
        {% endfor %}
    </div>

{% endblock content %}

context['posts']에 최근 블로그 포스트가 담겨져 있으므로 기존 페이지와 사용방법에 큰 차이는 없다. 

 

Routable Page는 Ajax 통신에도 사용가능하고 GET방식을 이용하여 Server와 Templates간의 데이터 송수신에도 편리하게 이용할 수 있을 것이다.

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

Wagtail 참고 사이트  (0) 2021.11.17
Wagtail git ignore setting  (0) 2021.11.16
Wagtail BaseSetting  (0) 2021.11.15
Wagtail Debug Toolbar(+ Django)  (0) 2021.11.13
Django, Wagtail Vue 로그인 연동  (0) 2021.11.12

+ Recent posts