[DMS]admin 페이지 커스터마이징 + 업로드 기능

포동동·2023년 4월 11일
0

🖱 우선 접속

우선, 서버를 켜주고 admin 페이지에 접속해본다.

$ python manage.py runserver
# http://127.0.0.1:8000/admin/로 접속

로그인 후 위와 같은 화면이 나온다면 성공이다.

왼쪽의 사이드바를 보면 기본적으로 wagtail이 제공해주는 기능들이 들어가있다. 오늘은 첫 화면과 사이드바를 커스터마이징 해보겠다. 기본적으로는 django의 상속 매커니즘을 따른다.


✨ 첫 화면 커스터마이징

우선, wagtail의 admin 페이지에서는 모든 페이지를 하나의 app으로 취급한다. 따라서 app을 하나 만들고 [프로젝트명]/settings/base.py로 들어가 그 app을 추가해준다. 만약 우선 만들어진 app 내에서 dashboard를 등록하고 싶다면 해당 app내의 templates/wagtailadmin/ 폴더를 만들어주면 된다. 이번에는 난 따로 app을 만들었다.

$ python manage.py startapp dashboard
# [프로젝트명]/settings/base.py
INSTALLED_APPS = [
    # ...

    'dashboard',

    'wagtail',
    'wagtail.admin',

    # ...
]

이제 준비는 끝났다. 그 다음, 아래와 같은 것들을 커스텀 할 수 있다.
1. 브랜딩 로고 변경
2. favicon 변경
3. admin 페이지 타이틀 변경
4. 로그인 페이지 변경
5. admin 페이지의 웰컴 메세지 변경

이것들은 전부 wagtailadmin이라는 app을 상속받아 커스텀 하는 것이다.


1. 브랜딩 로고 변경

dashboard/templates/wagtailadmin/base.html 파일을 만들고 아래와 같이 코드를 입력하고, dashboard/static/images 폴더 안에 원하는 이미지 파일을 저장한다.

<!-- 기본적으론 wagtailadmin app안의 base.html을 상속받아 사용한다 -->
{% extends "wagtailadmin/base.html" %}
{% load static %}

{% block branding_logo %}
    <img src="{% static 'images/[이미지 파일명]' %}" alt="Custom Project" width="80" />
{% endblock %}

이렇게 변경한 로고는 login 페이지, 404 페이지, wagtail userbar에 상속시킨다.


2. favicon 변경

dashboard/templates/wagtailadmin/admin_base.html 파일을 만들고 아래와 같이 코드를 입력한다. 편의상 나는 로고와 같은 이미지 파일로 넣었다.

{% extends "wagtailadmin/admin_base.html" %}
{% load static %}

{% block branding_favicon %}
    <link rel="shortcut icon" href="{% static 'images/[이미지 파일명]' %}" />
{% endblock %}

3. admin 페이지 타이틀 변경

favicon을 변경할 때와 같은 html 파일(dashboard/templates/wagtailadmin/admin_base.html)에 아래와 같이 코드를 추가한다.

{% block branding_title %}[넣고 싶은 문구]{% endblock %}

4. 로그인 페이지 변경

dashboard/templates/wagtailadmin/login.html 파일을 만들고 아래와 같이 코드를 입력한다.

{% extends "wagtailadmin/login.html" %}

{% block branding_login %}[넣고 싶은 문구2]{% endblock %}

5. admin 페이지의 웰컴 메세지 변경

dashboard/templates/wagtailadmin/home.html 파일을 만들고 아래와 같이 코드를 입력한다.

{% extends "wagtailadmin/home.html" %}

{% block branding_welcome %}[넣고 싶은 문구3]{% endblock %}

결과


무사히 커스텀이 된 것을 볼 수 있다. 만약 css를 수정하고 싶다면 dashboard/static/css 폴더를 만들어 css 파일을 작성한 뒤, 적용시키고 싶은 html 코드에 {% load static %}만 추가해주면 된다.


🎡 사이드바 커스텀 + 기능 구현

이제 본격적으로 기능들을 구현하기로 하자. 우선, 다시 한 번 구현해야 하는 기능들을 되짚어보면

  1. 파일을 업로드 할 수 있어야 한다.
  2. 지정한 조건에 따라 크롤링 할 수 있어야 한다.
  3. 조건에 따라 DB에서 조회할 수 있어야 한다.
  4. 조회한 데이터를 원하는 형식으로 다운로드 받을 수 있어야 한다.

이며, 나는 1번 기능을 upload라는 app, 2번 기능을 crawl이라는 app, 3번과 4번 기능을 retrieve라는 app으로 구현할 것이다.

우선, app을 생성해주고 [프로젝트명]/settings/base.py에 app을 등록한다.

$ python manage.py startapp upload
$ python manage.py startapp crawl
$ python manage.py startapp retrieve
# [프로젝트명]/settings/base.py
INSTALLED_APPS = [
    # ...

    'dashboard',
    "upload",
    "crawl",
    "retrieve"

    # ...
]

또 다시 준비가 끝났다. 이 다음, 우리는 admin 페이지의 사이드바에 해당 앱들을 등록해주어야 한다. 그 전에 이해해야 하는 개념이 있다. 바로 hook이다.

hook이란?

로드 시 Wagtail은 wagtail_hooks.py 파일이 있는 앱을 검색하여 내용을 실행합니다. 페이지를 저장하거나 메인 메뉴를 구성하는 등 Wagtail 실행의 특정 시점에서 실행할 수 있는 자체 기능을 등록하는 방법을 제공합니다.

라는 wagtail 공식문서의 설명이다. 간단하게 말하면 app들 중에 wagtail_hooks.py 파일이 있으면 사용자 정의 기능을 추가하고 wagtail에게 인식시킬 수 있다는 뜻이다.


이를 위해선 wagtail_hooks.py라는 파일을 app 안에 만들어야 한다. 원하는 app아래에 views.py랑 같은 레벨에 wagtail_hooks.py파일을 생성한 뒤 아래와 같이 코드를 작성한다.

from django.urls import path, reverse
from wagtail import hooks
from wagtail.admin.menu import MenuItem
from .views import index


@hooks.register('register_admin_urls')
def register_upload_url():
    return [
        path('upload/', index, name='upload')
    ]

@hooks.register('register_admin_menu_item')
def register_upload_menu_item():
    return MenuItem('Upload', reverse('upload'), icon_name='upload')

@hooks.register 데코레이션을 통해 admin 페이지에게 '여기도 app 있어요~~'라고 알려준다고 생각하면 된다. @hooks.register('register_admin_urls')을 통해 url을 추가해주고, @hooks.register('register_admin_menu_item')을 통해 사이드바 메뉴에 추가해준다.

그리고, MenuItem을 리턴할 때 url도 같이 전달해야 하는데, 그 때 사용하는게 바로 reverse이다. reverse는 Django에서 url을 역으로 검색할 떄 사용하는 함수로, url의 이름을 기반으로 url을 찾아내는 것이다. 즉, register_upload_url 함수를 통해 만들어낸 url을 name기반으로 다시 찾아내서 그 값을 리턴한다고 생각하면 된다.

그리고, icon_name으로 귀염뽀짝한 아이콘들도 커스텀 가능하다.


그 다음, upload 폴더 안에 templates/upload/index.html 파일을 만들어 준다.

{% extends "wagtailadmin/base.html" %} 
{% block content %} 
{% include "wagtailadmin/shared/header.html" %} {% load static %}

<div class="nice-padding">
<h2>파일 업로드</h2>
<form method="post" enctype="multipart/form-data">
  {% csrf_token %}
      <input type="file" name="upload" accept="">
      <button class="button button-secondary" type="submit">Submit</button>
</form>

{% endblock %}
  • {% extends "wagtailadmin/base.html" %}로 기본 틀을 상속받고
  • {% block content %}안에 원하는 요소들을 넣어주고,
  • {% include "wagtailadmin/shared/header.html" %}에서 header를 상속받아 요소들을 보기 좋은 위치에 놓고,
  • {% load static %}로 css와 js를 가져온다.

이 때, 주의할 점이 있다.

  • <form> 태그에서 enctype은 본인의 서비스 목적에 맞게 설정해야 한다. 나는 주로 json파일이나 텍스트 파일 등을 업로드 할 것이기 때문에 form-data를 사용했지만, 그 외의 경우도 있을 수 있기 때문에 꼭 확인하고 설정해준다.
  • <input> 태그에서 accept인자도 본인의 서비스 목적에 맞게 설정해야 한다. 이것도 똑같이 확인 후 설정한다.
  • 처음에 class나 id를 지정하지 않고 작성하면 못 생겼다. wagtail에서 제공하는 css가 입혀진 요소들을 보고싶다면, [프로젝트명]/settings/base.pyINSTALLED_APPS에 "wagtail.contrib.styleguide"를 추가해준다. 그 뒤에, admin 페이지의 사이바에서 Settings를 누른 뒤 맨 밑을 보면 styleguide 버튼이 추가된 것을 볼 수 있다. 거기서 원하는 요소의 class나 id 이름을 가져다 쓰면 된다.

그 다음, views.py파일에 가서 아래와 같이 코드를 작성한다.

from django.shortcuts import render
from django.core.files.storage import FileSystemStorage
import time

def index(request) :

    if request.method == 'POST' and request.FILES['upload']:

        start = time.time()

        upload = request.FILES['upload']
        fss = FileSystemStorage()
        file = fss.save(upload.name, upload)
        file_url = fss.url(file)

        end = time.time()
        total_time = end-start

        return render(request, 'upload/index.html', {'file_url': file_url, 'total_time':total_time})
        
    return render(request, 'upload/index.html')

간단하게 보자면, request.method가 POST이고, 전달받은 파일이 있을 때, upload라는 파일로 전달받아 fss.save를 통해 파일의 이름과 내용물을 전달한다. 그리고 걸린 시간과 파일이 저장된 url을 화면에 전달한다. 다시 한 번 index.html 파일에 가서 아래 코드와 같이 작성한다.


{% extends "wagtailadmin/base.html" %} 
{% block content %} 
{% include "wagtailadmin/shared/header.html" %} {% load static %}

<div class="nice-padding">
<h1 class="w-header__title" id="header-title">파일 업로드</h1>
<form method="post" enctype="multipart/form-data">
  {% csrf_token %}
      <input type="file" name="upload" accept="">
      <button class="button button-secondary" type="submit">Submit</button>
</form>

<!--추가된 부분-->
{% if file_url %}
<p>파일이 저장된 url : {{ file_url }}</p>
<p>총 {{ total_time }}초가 걸림</p>
{% endif %}
<!--추가된 부분-->

{% endblock %}

여기까지 하면, 아래와 같은 화면을 만날 수 있다. 나는 ㄴ.txt라는 파일을 임시로 넣어봤고, submit을 누르면 django 프로젝트 아래에 media라는 폴더가 새로 생성된 것을 알 수 있고, 거기에 파일이 들어가있을 것이다.

media가 저장되는 위치는 settings/base.py에서 수정 가능하다.

MEDIA_ROOT = os.path.join(BASE_DIR, "media")
MEDIA_URL = "/media/"

🎃 비슷하게 쫘좌작

해나가면 된다. 다음은 크롤링 하는 페이지와 데이터를 조회하는 페이지를 구현해보겠다.

profile
완료주의

0개의 댓글