Django Custom Template Tag를 이용한 Dynamic Navbar 만들기

navbar에 카테고리 필터항목을 집어넣고 싶은데 카테고리가 변경될때 마다 html작업을 하는게 매우 귀찮아서 실사용자가 하기 어려운 작업이기 때문에 자동으로 로드되는 카테고리 리스트가 필요했다.

기본적인 방법으로는 모든 view에 해당 queryset을 전달하여 처리하도록 할 수는 있으나 이것 또한 매우 귀찮아서 매우 비효율적이라고 느껴져 편하게 작업할 수 있는 번뜩이는 무언가가 필요해 작업을 하게되었다.

해당 내용을 알기전 어렵게 ajax요청으로 데이터를 받아와 jquery를 이용해 html tag를 구성 하여 기존 html에 append시키는 60줄이 넘는 코드에서 20줄이 내외정도 되는 코드로 해결을 할 수 있게 되었다.

또한 브라우저의 오류인지 재구성하여 만든 html태그가 이상없이 작성했음에도 불구하고 OnMouseOver옵션이 됐다가 안됐다가 하는 이상한 버그도 해결할 수 있었다. (이것때문에 4시간을 넘게 고생했다 왜 진작 공부하지 않았고 찾아보지 않았는지 후회중이다)

custom template tag 공식문서

templatetags python 패키지 생성

  1. templatetags python 패키지를 생성합니다.

     app/
         __init__.py
         models.py
         ...
         templatetags/
             __init__.py
             custom_tags.py
    
  2. 불러오는 위치는 상관 없지만 기본적으로 djangoapp안에 templatetags라는 python 패키지로 만들어야 합니다.
    ex) blog app에 만들고 base.html에 적용시켜 어디서든 불러올 수 있습니다. 관련있는 app에 생성하면 좋을 것 같습니다.

template tag생성

  1. 아래와 같이 template_tag를 생성합니다.

     from django import template
     register = template.Library()
    	
     @register.assignment_tag
     def blog_categories():
         return BlogMainCategory.objects.all()
    	
    
  2. assignment_tag를 사용하는 것은 템플릿에서 템플릿변수 처럼 사용할 수 있어서입니다.
  3. 표기법은 {% tag명 as 변수명 %} 입니다.

실제 적용 코드

{% blog_categories as blog_category_list %}
<ul class="submenu">
    {% for blog_category in blog_category_list %}
        <li class="has-submenu">
            <a href="">{{ blog_category }}</a>
            <ul class="submenu">
                {% for subcategory in blog_category.blogsubcategory_set.all %}
                    <li><a href="{{ subcategory.get_absolute_url }}">{{ subcategory.name }}</a></li>
                {% endfor %}
            </ul>
        </li>
    {% endfor %}
</ul>

AWS의 RDS기준으로 작성하였습니다.

MySQL사용시 한글 깨짐 증상 해결 방법

파라미터 그룹 생성

  1. RDS console아래의 파라미터 그룹에 들어갑니다.
  2. 파라이터 그룹 생성에 들어갑니다. 파라미터 그룹
  3. 그룹 패밀리는 mysql5.6으로 지정합니다.
  4. 그룹 이름을 지정합니다.(해당 블로그에서는 mysql-utf-8로 생성하였습니다.) 파라미터 그룹 생성
  5. 생성한 파라미터 그룹에 들어갑니다.
  6. 파라미터 편집을 클릭합니다.
  7. 다음과 같이 수정을 합니다.

     character_set_database = utf8
     character_set_server = utf8
     collation_connection = utf8_general_ci
     collation_server = utf8_general_ci
    
  8. 변경내용을 저장합니다.

MySQL 인스턴스 생성

MySQL생성 후에 파라미터 그룹을 수정하게 되면 일부 언어 설정이 바뀌지 않아 동일하게 한글이 정상적으로 적용되지 않아 새로운 인스턴스 생성이 필요합니다.

  1. RDS인스턴스 탭에 들어갑니다.
  2. DB 인스턴스 시작을 누릅니다. RDS 인스턴스
  3. MySQL을 선택하고 다음을 누릅니다.
  4. 고급 설정 구성데이터베이스 옵션항목에서 DB파라미터 그룹을 생성한 파라미터 그룹으로 변경합니다. 파라미터 그룹 지정
  5. DB인스턴스를 생성합니다.

정보 확인

  1. 정보 확인
  2. mysql utility를 이용해 mysql의 db에 연결 합니다.MySQL 연결 가이드
  3. 하기 명령어를 입력합니다. mysql> show variables like 'c%';
  4. 아래의 사진과 같이 latin항목이 없이 모두 utf8로 잘 나오는지 확인합니다. 확인

ㅜㄹ

Django-extensions를 이용한 ERD만들기

django-extentions graph_model 공식 문서

Django extensions 설치

pip를 이용해 django-extions를 설치합니다.
$ pip install django-extionsions

settins.py의 INSTALLED_APPS에 django_extensions를 넣어줍니다.

# settions.py
INSTALLED_APPS = (
    ...
    'django_extensions',
)

그룹모델 지정

# settings.py
GRAPH_MODELS = {
  'all_applications': True,
  'group_models': True,
}

기본적으로 Django-extensions에 있는 graph model기능을 이용해 dot파일을 생성할 수 있습니다.

$ ./manage.py graph_models -a > my_project.dot

dotfile

위와 같이 기본적으로 볼 수는 있으나 보기가 편하지는 않습니다. 조금 더 이쁘게 보기 위해 graphviz 설치가 필요합니다.

graphviz

공식문서에는 $ pip install pygraphviz를 하면 된다고 나와 있으나 그냥 설치를 하게 되면 오류가 발생을 합니다.

brew를 통한 graphviz설치가 선행이 되어야합니다.

$ brew install graphviz

설치가 완료된 후 $ pip install pygraphviz

$ /manage.py graph_models -a -g -o my_project_visualized.png

graphviz

위와 같이 그림으로 조금 더 보기 쉽게 바꿀 수 있습니다.

원하는 모델만 출력하기

위의 사진에서 보게 되면 Django에서 기본적으로 만들어놓은 여러 모델들때문에 보기가 이쁘지는 않습니다.

원하는 모델만 출력을 하도록 변경을 해봅니다.

$ ./manage.py graph_models -a -I User,Center,WorkOutRecord -o my_project_want_model.png

justwantmodel

One Page 사이트 외주 후기

사이트 정보

Python 3.6.3, Django 2.0.1, Bootstrap 3.3 등을 이용해 지인이 부탁한 개인 사이트를 개발하였습니다.
개발 기간은 생각보다 할 작업이 많아 여유롭게 진행을 하다보니 3주 정도 개발을 하였습니다.
현재 개발은 거의 완료 되어 있는 상태고 일부 조정 사항이 남아 현재는 pythonanywhere에 올라가 있습니다.

기능

기본적인 개인 소개 페이지로 특별한 기능이 많지는 않습니다.

  • Image slide
  • 운동영상을 youtube에 올린 후 운동 정보 model에 넣게되면 youtube 영상의 thumbnail을 받아와 저장
  • 주소 입력시 requests를 이용하여 google geocoding에서 위경도를 받아와 저장, 받아 온 위경도를 이용하여 페이지에 표시
  • Q & A의 Pagination

어려웠던점

HTML

https://wrapbootstrap.com/에서 템플릿을 사다가 작업을 하다보니 생각보다 처음 코드를 읽고 정리를 하는 부분이 시간이 많이 소요된다는 걸 알았습니다.

그리고 있는 기능을 쓰는 것은 편하지만 뭔가 커스터마이징을 하려고 하면 생각지도 못한 다른 일들이 생기는 것을 보고 쉽지는 않구나 하는 생각을 하였습니다.

HTML, Css 및 Bootstrap을 그래도 잘 활용할 줄 알고 있다고 생각을 했는데, 아직 많이 부족하다는 것을 깨달았습니다.

오류처리

QuestionForm에서 errors를 갖고 리턴을 해줄 수 있도록 로직은 구현을 했지만 Form참을 modal형태로 띄워주다보니 리턴시 modal창이 뜨지 않아서 새로 눌러야하는 번거로움이 있었습니다.

해당 내용은 다음과 같이 jquery를 이용해 form.error가 있을 경우 modal의 show 옵션을 이용해 처리 하도록 하였습니다.


{% if question_form.errors %}
    <script>
        $(function () {
            $('#question-form').modal({show: true});
        });
	</script>
{% endif %}

이와 같이 처리는 하였으나

CommentForm은 물론 Admin만 작성을 할 수 있으며, TextInput만 받으면 되어 오류가 발생을 하지는 않을 것이나, 혹시 모르는 상황에 대해 위의 QuestionForm처럼 작업을 하려고 하였으나, CommentForm 자체가 Question 별로 달려 있다보니 모두 id가 똑같이 되도록 되어 있어 오류 상황에 대처하기 어려웠습니다. - id를 여러개 만드는 방법은 고민중에 있습니다.

다음부터는 원페이지 사이트를 안만드는게 정신건강에 이로울 것 같습니다

해당 내용은 조금더 공부가 필요할 것 같습니다.

푸념

이번 작업을 하다보니 코딩을 하지 않는 사람과의 의견 조율이 생각보다 어려웠습니다.
처음 시작시에는 Q & A기능이 없었다가 나중에 추가가 되면서 기존에 하던 방식과 다르게 One Page에서 해결방법을 찾아야되다보니 생각보다 어려웠습니다.

그로 인해 깨닫게 된 것은 사전에 프로젝트에 들어가기전에 의견을 완벽하게 조율하고, 의견 조율에 들이는 시간을 아까워하지 말아야한다 는 점을 깨달 았습니다.

간단한 사이트임에도 이러헤 힘들어 하는 것을 보고, 추후 이런 외주 업무를 통해서 돈을 벌려면 공부를 한참 더 열심히 해야된다는 것을 한번더 새삼 느끼게한 시간이였습니다.

django bootstrap pagination package

사용법

django-bootstrap-pagination

if 문을 사용해서 복잡하게 사용해야했던 Pagination 기능을 한줄로 간단하게 처리할 수 있게 해줌

  • 기본

        
     {% bootstrap_paginate page_obj %}
        
    

    한줄만 적으면 끝

  • range: 밑에 버튼으로 몇개를 표시해줄건지 범위를 정할 수 있음

        
      {% bootstrap_paginate page_obj range=숫자 %}
        
    
  • show_prev_next: 이전 버튼, 다음버튼 표시 여부

        
      {% bootstrap_paginate page_obj show_prev_next="불리언" %}
        
    
  • show_first_last: 처음과 마지막 버튼 표시 여부

        
      {% bootstrap_paginate page_obj show_first_last="불리언" %}
        
    
  • 각종 파라미터 및 url변경 기능을 추가할 수 있어 편함

Django 1.10+ 버전의 호환성 오류 확인

urlreslovers django import Error 발생함 확인

django 1.10이후 django.core.urlresolversdjango.urls로 변경됨

import 부분 해결 후 사용시 정상작동

기존코드

# bootstrap_pagination.py

from django.core.urlresolvers import reverse, NoReverseMatch

변경코드

try:
	from django.core.urlresolvers import reverse, NoReverseMatch
except ImportError:
	from django.urls import reverse, NoReverseMatch
contibute 해보려고 했으나 이미 누군가 12월에 같은 코드로 pull requests 날렸던건 안비밀

package가 잘 관리는 안되고 있으나 편하고 좋습니다.