Skip to content

플러그인 제작

demo_plugin 플러그인을 기반으로 사용자 임의의 플러그인을 제작하는 과정을 소개합니다.

주의사항

  • 개별 플러그인 자체 오류가 있을 경우, 그누보드6 시작에 영향을 줄 수 있습니다.
  • router 함수의 url이 중복되면 기존 페이지 대신 플러그인 페이지가 표시됩니다.

플러그인 폴더 추가

demo_plugin 폴더를 복사하여 plugin 폴더에 추가합니다. 다른 플러그인과 겹치지 않도록 알파벳 + 숫자 조합으로 고유한 이름으로 지어주세요.

관리자 페이지

1. 관리자 메뉴 주소등록

플러그인에서 사용할 name, url, tag를 수정합니다.

  • name: 관리자 페이지에서 표시할 이름입니다.
  • url: 관리자 페이지에서 접근할 수 있는 주소입니다.
  • tag: 라우터에서 사용할 태그입니다. 중복되지 않도록 고유한 값을 사용해주세요.
plugin/{플러그인 이름}/plugin_config.py
admin_menu = {
        f"{module_name}": [
            {
                "name": "플러그인 테스트",
                "url": "",
                "tag": "",
            },
            {
                "id": module_name + "1",
                "name": "플러그인 테스트 메뉴1",
                "url": f"{admin_router_prefix}/test_plugin_json",
                "tag": "demo1",
            },
            {
                "id": module_name + "2",
                "name": "플러그인 테스트 메뉴2",
                "url": f"{admin_router_prefix}/test_plugin",
                "tag": "demo2",
            },
        ]
    }

관리자메뉴 id 중복 주의

id 값은 module_name + 숫자 조합으로 고유한 값을 사용해주세요. 기존 관리자 메뉴와 중복되면 정상적으로 표시되지 않거나 권한 등에 문제가 생길 수 있습니다.
admin/admin_menu_bbs.json 파일에 등록된 메뉴를 참고하시면 됩니다.

관리자 메뉴 등록 처리

  • admin_menu에 등록한 메뉴는 admin > __init__.py > register_admin_menu() 함수를 통해 추가됩니다.

2. 관리자 라우터 설정

@admin_router.get()의 주소를 관리자페이지 메뉴에서 등록한 url과 일치하도록 수정합니다.

plugin/{플러그인 이름}/admin/admin_router.py
@admin_router.get("/test_plugin_json")
async def show(request: Request):
    request.session["menu_key"] = module_name
    request.session["plugin_submenu_key"] = module_name + "1"

    return {
        "message": "Hello Admin Demo Plugin!",
        "pacakge": __package__,
        "__file__": __file__,
        "__name__": __name__,
    }

@admin_router.get("/test_plugin")
async def show(request: Request):
    request.session["menu_key"] = module_name
    request.session["plugin_submenu_key"] = module_name + "2"

    context = {
        "request": request,
        "title": "Hello Admin demo Plugin!",
        "content": f"Hello {module_name}",
        "module_name": module_name,
    }
    return templates.TemplateResponse(f"{plugin_config.TEMPLATE_PATH}/admin/admin_demo.html", context)

3. 플러그인 정보 변경

3-1. 정보 변경

플러그인의 제작 정보를 변경합니다. 이 정보는 관리자페이지에서 확인할 수 있습니다.

plugin/{플러그인 이름}/readme.txt
plugin Name: 플러그인 테스트
plugin URI: gnuboard.com
Maker: GNUBOARD
Maker URI: gnuboard.com
Version: 1.0.0
Detail: 테스트 플러그인 입니다.
License: MIT
License URI: https://opensource.org/license/mit/

3-2. 스크린샷 변경

screenshot.png 파일을 플러그인의 스크린샷으로 변경합니다.

Image title

예) 플러그인 상세화면

4. 플러그인 활성화

  • 추가한 플러그인이 목록에 표시되었습니다.
  • 관리자페이지 > 환경설정 > 플러그인 관리에서 플러그인 적용 버튼을 눌러 플러그인을 활성화합니다.

Image title

플러그인 목록 화면

플러그인이 활성화되면 버튼 변경 및 좌측 메뉴에 플러그인이 추가됩니다.

Image title

플러그인 활성화

플러그인이 정상적으로 등록됬다면 관리자페이지에서 플러그인을 확인할 수 있습니다.

Image title

플러그인 페이지

사용자페이지

관리자 라우터 설정

@router.get()의 주소를 사용자페이지에서 접근할 수 있는 주소로 변경합니다.

plugin/{플러그인 이름}/user_router.py
@router.get("/show")
async def show(request: Request):
    """json 출력예시"""
    return {"message": "Hello Plugin JSON!"}

@router.get("/show_template")
async def show(request: Request):
    """템플릿 출력예시"""
    return templates.TemplateResponse(
        f"{plugin_config.TEMPLATE_PATH}/user_demo.html",
        {
            "request": request,
            "title": "Hello plugin Template!",
            "content": f"Hello {module_name}!",
        })

사용자 router 등록 처리

  • router 함수는 user > __init__.py > register_user_router() 함수를 통해 등록됩니다.

Image title

플러그인 사용자 페이지

모델 추가 (데이터베이스 테이블)

플러그인에서 사용할 데이터베이스 모델을 추가할 수 있습니다.

plugin/{플러그인 이름}/models.py
from datetime import datetime

from sqlalchemy import Column, Integer, String, Boolean, DateTime, Text

from core.database import DBConnect
from core.models import Base


class Todo(Base):
    __tablename__ = DBConnect().table_prefix + "{테이블 이름}"

    id = Column(Integer, primary_key=True, index=True)
    title = Column(String(length=50), index=True)
    content = Column(Text)
    is_done = Column(Boolean, default=False)
    created_at = Column(DateTime, default=datetime.now)