gnuboard / g6 Goto Github PK
View Code? Open in Web Editor NEW파이썬 게시판 그누보드6 : GNUBOARD6 is Python CMS with fastapi
Home Page: https://sir.kr
License: MIT License
파이썬 게시판 그누보드6 : GNUBOARD6 is Python CMS with fastapi
Home Page: https://sir.kr
License: MIT License
"접근 권한이 없습니다." 경고창 출력후 글 쓰기가 됩니다.
with SessionLocal() as db:
config = db.query(Config).first()
register_social_provider(config)
config = db.query(Config).first()
이 코드를 다른 코드로 수정 바랍니다.
관리권한 설정을 하지 않은 회원도 관리자 메인 접근이 가능하네요.
auth
포인트 관련된 작업 하고 있으니 작업 겹치지 않도록 주의하세요.
write_model = dynamic_create_write_table(new.bo_table)
model_write = dynamic_create_write_table(new.bo_table)
models_write = dynamic_create_write_table(new.bo_table)
File "admin/templates/board_list.html", line 1, in top-level template code
{% extends "base.html" %}
File "admin/templates/base.html", line 175, in top-level template code
{% block content %}{% endblock %}
File "admin/templates/board_list.html", line 71, in block 'content'
{{ get_skin_select('board', 'bo_mobile_skin[]', board.bo_mobile_skin, event='required', device='mobile')|safe }}
File "/home/ubuntu/gnu6/lib/common.py", line 182, in get_skin_select
for skin in os.listdir(skin_path):
FileNotFoundError: [Errno 2] No such file or directory: 'templates/basic/mobile/board'
master 를 새로 pull 한 후 새로 설치하여 테스트 해보세요.
Traceback (most recent call last):
File "/home/ubuntu/.local/lib/python3.10/site-packages/uvicorn/protocols/http/httptools_impl.py", line 426, in run_asgi
result = await app( # type: ignore[func-returns-value]
File "/home/ubuntu/.local/lib/python3.10/site-packages/uvicorn/middleware/proxy_headers.py", line 84, in __call__
return await self.app(scope, receive, send)
File "/home/ubuntu/.local/lib/python3.10/site-packages/fastapi/applications.py", line 292, in __call__
await super().__call__(scope, receive, send)
File "/home/ubuntu/.local/lib/python3.10/site-packages/starlette/applications.py", line 122, in __call__
await self.middleware_stack(scope, receive, send)
File "/home/ubuntu/.local/lib/python3.10/site-packages/starlette/middleware/errors.py", line 184, in __call__
raise exc
File "/home/ubuntu/.local/lib/python3.10/site-packages/starlette/middleware/errors.py", line 162, in __call__
await self.app(scope, receive, _send)
File "/home/ubuntu/.local/lib/python3.10/site-packages/starlette/middleware/base.py", line 108, in __call__
response = await self.dispatch_func(request, call_next)
File "/home/ubuntu/gnu6/core/middleware.py", line 68, in core_middleware
return await call_next(request)
File "/home/ubuntu/.local/lib/python3.10/site-packages/starlette/middleware/base.py", line 84, in call_next
raise app_exc
File "/home/ubuntu/.local/lib/python3.10/site-packages/starlette/middleware/base.py", line 70, in coro
await self.app(scope, receive_or_disconnect, send_no_error)
File "/home/ubuntu/.local/lib/python3.10/site-packages/starlette/middleware/base.py", line 108, in __call__
response = await self.dispatch_func(request, call_next)
File "/home/ubuntu/gnu6/core/middleware.py", line 101, in dispatch
return await call_next(request)
File "/home/ubuntu/.local/lib/python3.10/site-packages/starlette/middleware/base.py", line 84, in call_next
raise app_exc
File "/home/ubuntu/.local/lib/python3.10/site-packages/starlette/middleware/base.py", line 70, in coro
await self.app(scope, receive_or_disconnect, send_no_error)
File "/home/ubuntu/.local/lib/python3.10/site-packages/starlette/middleware/sessions.py", line 86, in __call__
await self.app(scope, receive, send_wrapper)
File "/home/ubuntu/.local/lib/python3.10/site-packages/starlette/middleware/base.py", line 108, in __call__
response = await self.dispatch_func(request, call_next)
File "/home/ubuntu/gnu6/main.py", line 211, in main_middleware
response: Response = await call_next(request)
File "/home/ubuntu/.local/lib/python3.10/site-packages/starlette/middleware/base.py", line 84, in call_next
raise app_exc
File "/home/ubuntu/.local/lib/python3.10/site-packages/starlette/middleware/base.py", line 70, in coro
await self.app(scope, receive_or_disconnect, send_no_error)
File "/home/ubuntu/.local/lib/python3.10/site-packages/starlette/middleware/exceptions.py", line 79, in __call__
raise exc
File "/home/ubuntu/.local/lib/python3.10/site-packages/starlette/middleware/exceptions.py", line 68, in __call__
await self.app(scope, receive, sender)
File "/home/ubuntu/.local/lib/python3.10/site-packages/fastapi/middleware/asyncexitstack.py", line 20, in __call__
raise e
File "/home/ubuntu/.local/lib/python3.10/site-packages/fastapi/middleware/asyncexitstack.py", line 17, in __call__
await self.app(scope, receive, send)
File "/home/ubuntu/.local/lib/python3.10/site-packages/starlette/routing.py", line 718, in __call__
await route.handle(scope, receive, send)
File "/home/ubuntu/.local/lib/python3.10/site-packages/starlette/routing.py", line 276, in handle
await self.app(scope, receive, send)
File "/home/ubuntu/.local/lib/python3.10/site-packages/starlette/routing.py", line 66, in app
response = await func(request)
File "/home/ubuntu/.local/lib/python3.10/site-packages/fastapi/routing.py", line 273, in app
raw_response = await run_endpoint_function(
File "/home/ubuntu/.local/lib/python3.10/site-packages/fastapi/routing.py", line 190, in run_endpoint_function
return await dependant.call(**values)
File "/home/ubuntu/gnu6/bbs/board.py", line 867, in read_post
insert_point(request, mb_id, read_point, f"{board.bo_subject} {write.wr_id} 글읽기", board.bo_table, write.wr_id, "읽기")
File "/home/ubuntu/gnu6/lib/common.py", line 880, in insert_point
db.commit()
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/orm/session.py", line 1969, in commit
trans.commit(_to_root=True)
File "<string>", line 2, in commit
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/orm/state_changes.py", line 139, in _go
ret_value = fn(self, *arg, **kw)
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/orm/session.py", line 1256, in commit
self._prepare_impl()
File "<string>", line 2, in _prepare_impl
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/orm/state_changes.py", line 139, in _go
ret_value = fn(self, *arg, **kw)
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/orm/session.py", line 1231, in _prepare_impl
self.session.flush()
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/orm/session.py", line 4312, in flush
self._flush(objects)
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/orm/session.py", line 4447, in _flush
with util.safe_reraise():
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/util/langhelpers.py", line 146, in __exit__
raise exc_value.with_traceback(exc_tb)
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/orm/session.py", line 4408, in _flush
flush_context.execute()
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/orm/unitofwork.py", line 466, in execute
rec.execute(self)
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/orm/unitofwork.py", line 642, in execute
util.preloaded.orm_persistence.save_obj(
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/orm/persistence.py", line 93, in save_obj
_emit_insert_statements(
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/orm/persistence.py", line 1226, in _emit_insert_statements
result = connection.execute(
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/engine/base.py", line 1416, in execute
return meth(
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/sql/elements.py", line 516, in _execute_on_connection
return connection._execute_clauseelement(
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/engine/base.py", line 1639, in _execute_clauseelement
ret = self._execute_context(
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/engine/base.py", line 1820, in _execute_context
self._handle_dbapi_exception(
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/engine/base.py", line 2343, in _handle_dbapi_exception
raise sqlalchemy_exception.with_traceback(exc_info[2]) from e
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/engine/base.py", line 1814, in _execute_context
context = constructor(
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/engine/default.py", line 1455, in _init_compiled
l_param: List[Any] = [
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/engine/default.py", line 1456, in <listcomp>
flattened_processors[key](compiled_params[key])
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/dialects/sqlite/base.py", line 1142, in process
raise TypeError(
sqlalchemy.exc.StatementError: (builtins.TypeError) SQLite Date type only accepts Python date objects as input.
[SQL: INSERT INTO g6_point (mb_id, po_datetime, po_content, po_point, po_use_point, po_expired, po_expire_date, po_mb_point, po_rel_table, po_rel_id, po_rel_action) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)]
[parameters: [{'po_mb_point': 219, 'po_content': '질문답변 1 글읽기', 'po_rel_id': '1', 'po_rel_table': 'qa', 'po_datetime': datetime.datetime(2024, 1, 3, 15, 44, 48, 225496), 'po_expire_date': '2024-01-03', 'po_use_point': 0, 'po_rel_action': '읽기', 'mb_id': 'admin', 'po_point': -1, 'po_expired': 1}]]
dataclasses 적용 및 마무리 작업 진행
dataclassform.py 에 폼 관련 class 생성하세요.
_admin/admin_config.py 반영 완료 (참고하세요)
data 디렉토리는 git clone 시 자동으로 생성되지 않습니다.
HTTP
로 실행되어 FastAPI에서 사용하는 base_url이 http로 설정됨.HTTPS
로 실행uvicorn main:app --reload --ssl-keyfile=./key.pem --ssl-certfile=./cert.pem
python deployment.py
# deployment.py
import uvicorn
if __name__ == "__main__":
uvicorn.run("main:app", port=8000, reload=True, ssl_keyfile="key.pem", ssl_certfile="cert.pem")
try:
import jinja2
if hasattr(jinja2, "pass_context"):
pass_context = jinja2.pass_context
else: # pragma: nocover
pass_context = jinja2.contextfunction # type: ignore[attr-defined]
except ImportError: # pragma: nocover
jinja2 = None # type: ignore
@pass_context
def url_for(context: dict, name: str, **path_params) -> str:
request = context["request"]
http_url = request.url_for(name, **path_params)
if request.url.scheme == 'https' or "x-forwarded-for" in request.headers.keys():
return http_url.__str__().replace("http", "https", 1)
else:
return http_url
class MyTemplates(Jinja2Templates):
"""
Jinja2Template 설정 클래스
"""
def __init__(self,
directory: Union[str, os.PathLike],
context_processors: dict = None,
globals: dict = None,
env: Environment = None
):
super().__init__(directory=directory, context_processors=context_processors)
# 공통 env.global 설정
self.env.globals["editor_path"] = editor_path
self.env.globals["generate_token"] = generate_token
self.env.globals["getattr"] = getattr
self.env.globals["get_selected"] = get_selected
self.env.globals["get_member_icon"] = get_member_icon
self.env.globals["get_member_image"] = get_member_image
self.env.globals["url_for"] = url_for
...
admin/write_count
확인 바랍니다.
php 그누보드5를 참고하세요.
/admin/write_count
지금은 모든 브라우저가 placeholder 를 지원할테니까요.
겹치지 않게 작업하세요
방법이 있다면 알려주세요.
에러로 인식할 수 있으므로 이 메세지 나오지 않게 조치 바랍니다.
회원 탈퇴 시 백엔드를 통해 g6_member 테이블의 mb_leave_date에 입력되는 값은 '2023-12-21'와 같이 10 글자임 (코드 참고)
# bbs/member_leave.py
@router.post("/member_leave", dependencies=[Depends(validate_token)])
async def member_leave(
...
leave_date = datetime.now().strftime("%Y-%m-%d") # 10 글자로 생성 ex) 2023-12-22
memo = f"{login_member.mb_memo}\n{leave_date}탈퇴함"
db.execute(
update(Member)
.values(mb_leave_date=leave_date, mb_memo=memo) # 8글자 제약조건의 mb_leave_date에 10글자 leave_date 값 입력
.where(Member.mb_id == login_member.mb_id)
)
컬럼 제약조건은 varchar(8)로 8글자라서 아래와 같은 오류 발생
sqlalchemy.exc.DataError: (pymysql.err.DataError) (1406, "Data too long for column 'mb_leave_date' at row 1")
그누보드 5 DB도 해당 컬럼의 제약조건이 varchar(8)이므로 호환성을 고려하여 수정해야 할 것으로 보임
그누보드5 참고해서 나머지 부분 작업하세요
visit_list (참고)
visit_domain
visit_browser
visit_os
visit_device
visit_hour
visit_week
visit_date
visit_month
visit_year
사용하지 않는 함수라면 삭제해 주세요.
function dataFeed( opts, callback ) {
var data = [];
if (opts.marker == "@" && opts.query) {
var thisVal = opts.query,
srcRegex = /<img.*?src=["'](.*?)["']/;
ck_itemsMentions = ck_cachequeryMentions[thisVal];
if(typeof ck_itemsMentions == "object"){
callback(ck_itemsMentions);
} else {
var data_url = g5_plugin_url+"/mention/q.php";
/bbs/point.py 복사 후 작업 예정
모바일에 맞는 UI 로 수정 바랍니다.
확인 바랍니다.
DB 또는 테이블이 존재하지 않습니다.
설치를 진행해 주세요.
python3 install.py
위 메세지가 나오도로고
shell 에서 print 문으로 처리
에러 메세지
INFO: 59.10.38.107:0 - "POST /board/write_comment_update/ HTTP/1.0" 500 Internal Server Error
ERROR: Exception in ASGI application
Traceback (most recent call last):
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/engine/base.py", line 1969, in _exec_single_context
self.dialect.do_execute(
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/engine/default.py", line 922, in do_execute
cursor.execute(statement, parameters)
sqlite3.OperationalError: near "(": syntax error
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/home/ubuntu/.local/lib/python3.10/site-packages/uvicorn/protocols/http/httptools_impl.py", line 426, in run_asgi
result = await app( # type: ignore[func-returns-value]
File "/home/ubuntu/.local/lib/python3.10/site-packages/uvicorn/middleware/proxy_headers.py", line 84, in __call__
return await self.app(scope, receive, send)
File "/home/ubuntu/.local/lib/python3.10/site-packages/fastapi/applications.py", line 292, in __call__
await super().__call__(scope, receive, send)
File "/home/ubuntu/.local/lib/python3.10/site-packages/starlette/applications.py", line 122, in __call__
await self.middleware_stack(scope, receive, send)
File "/home/ubuntu/.local/lib/python3.10/site-packages/starlette/middleware/errors.py", line 184, in __call__
raise exc
File "/home/ubuntu/.local/lib/python3.10/site-packages/starlette/middleware/errors.py", line 162, in __call__
await self.app(scope, receive, _send)
File "/home/ubuntu/.local/lib/python3.10/site-packages/starlette/middleware/sessions.py", line 86, in __call__
await self.app(scope, receive, send_wrapper)
File "/home/ubuntu/.local/lib/python3.10/site-packages/starlette/middleware/base.py", line 108, in __call__
response = await self.dispatch_func(request, call_next)
File "/home/ubuntu/gnu6/main.py", line 260, in main_middleware
response = await call_next(request)
File "/home/ubuntu/.local/lib/python3.10/site-packages/starlette/middleware/base.py", line 84, in call_next
raise app_exc
File "/home/ubuntu/.local/lib/python3.10/site-packages/starlette/middleware/base.py", line 70, in coro
await self.app(scope, receive_or_disconnect, send_no_error)
File "/home/ubuntu/.local/lib/python3.10/site-packages/starlette/middleware/base.py", line 108, in __call__
response = await self.dispatch_func(request, call_next)
File "/home/ubuntu/gnu6/main.py", line 95, in dispatch
return await call_next(request)
File "/home/ubuntu/.local/lib/python3.10/site-packages/starlette/middleware/base.py", line 84, in call_next
raise app_exc
File "/home/ubuntu/.local/lib/python3.10/site-packages/starlette/middleware/base.py", line 70, in coro
await self.app(scope, receive_or_disconnect, send_no_error)
File "/home/ubuntu/.local/lib/python3.10/site-packages/starlette/middleware/exceptions.py", line 79, in __call__
raise exc
File "/home/ubuntu/.local/lib/python3.10/site-packages/starlette/middleware/exceptions.py", line 68, in __call__
await self.app(scope, receive, sender)
File "/home/ubuntu/.local/lib/python3.10/site-packages/fastapi/middleware/asyncexitstack.py", line 20, in __call__
raise e
File "/home/ubuntu/.local/lib/python3.10/site-packages/fastapi/middleware/asyncexitstack.py", line 17, in __call__
await self.app(scope, receive, send)
File "/home/ubuntu/.local/lib/python3.10/site-packages/starlette/routing.py", line 718, in __call__
await route.handle(scope, receive, send)
File "/home/ubuntu/.local/lib/python3.10/site-packages/starlette/routing.py", line 276, in handle
await self.app(scope, receive, send)
File "/home/ubuntu/.local/lib/python3.10/site-packages/starlette/routing.py", line 66, in app
response = await func(request)
File "/home/ubuntu/.local/lib/python3.10/site-packages/fastapi/routing.py", line 273, in app
raw_response = await run_endpoint_function(
File "/home/ubuntu/.local/lib/python3.10/site-packages/fastapi/routing.py", line 190, in run_endpoint_function
return await dependant.call(**values)
File "/home/ubuntu/gnu6/bbs/board.py", line 1123, in write_comment_update
comment.wr_comment_reply = generate_reply_character(board, parent_comment)
File "/home/ubuntu/gnu6/lib/board_lib.py", line 891, in generate_reply_character
result = query.order_by(desc("reply")).first()
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/orm/query.py", line 2748, in first
return self.limit(1)._iter().first() # type: ignore
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/orm/query.py", line 2847, in _iter
result: Union[ScalarResult[_T], Result[_T]] = self.session.execute(
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/orm/session.py", line 2308, in execute
return self._execute_internal(
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/orm/session.py", line 2190, in _execute_internal
result: Result[Any] = compile_state_cls.orm_execute_statement(
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/orm/context.py", line 293, in orm_execute_statement
result = conn.execute(
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/engine/base.py", line 1416, in execute
return meth(
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/sql/elements.py", line 516, in _execute_on_connection
return connection._execute_clauseelement(
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/engine/base.py", line 1639, in _execute_clauseelement
ret = self._execute_context(
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/engine/base.py", line 1848, in _execute_context
return self._exec_single_context(
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/engine/base.py", line 1988, in _exec_single_context
self._handle_dbapi_exception(
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/engine/base.py", line 2343, in _handle_dbapi_exception
raise sqlalchemy_exception.with_traceback(exc_info[2]) from e
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/engine/base.py", line 1969, in _exec_single_context
self.dialect.do_execute(
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/engine/default.py", line 922, in do_execute
cursor.execute(statement, parameters)
sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) near "(": syntax error
[SQL: SELECT right(g6_write_notice.wr_comment_reply, ?) AS reply
FROM g6_write_notice
WHERE g6_write_notice.wr_parent = ? AND g6_write_notice.wr_comment = ? AND length(g6_write_notice.wr_comment_reply) = ? ORDER BY reply DESC
LIMIT ? OFFSET ?]
[parameters: (1, 4, 1, 1, 1, 0)]
(Background on this error at: https://sqlalche.me/e/20/e3q8)
공통 검색 파라미터를 사용시
async def member_list(request: Request, db: Session = Depends(get_db), search_params: dict = Depends(common_search_query_params)):
select query 시
result = select_query(
request,
models.Member,
search_params,
same_search_fields = ["mb_level"],
prefix_search_fields = ["mb_name", "mb_nick", "mb_tel", "mb_hp", "mb_datetime", "mb_recommend"]
)
same_search_fields: # 값이 완전히 같아야지만 필터링 '검색어'
prefix_search_fields: # 뒤에 %를 붙여서 필터링 '검색어%'
수정된 회원 관리 리스트 코드
@router.get("/member_list")
async def member_list(request: Request, db: Session = Depends(get_db), search_params: dict = Depends(common_search_query_params)):
'''
회원관리 목록
'''
request.session["menu_key"] = MEMBER_MENU_KEY
result = select_query(
request,
models.Member,
search_params,
same_search_fields = ["mb_level"],
prefix_search_fields = ["mb_name", "mb_nick", "mb_tel", "mb_hp", "mb_datetime", "mb_recommend"]
)
query_string = generate_query_string(request)
context = {
"request": request,
"members": result['rows'],
"admin": request.state.context['member'], # 로그인해 있는 회원을 관리자로 간주함
"total_count": result['total_count'],
"paging": get_paging(request, search_params['current_page'], result['total_count'], f"/admin/member_list?{query_string}&page="),
}
return templates.TemplateResponse("member_list.html", context)
db.query(model)
이 legacy 표현식으로 분류됨.# www.gnuboard.com 과 gnuboard.com 도메인은 서로 다른 도메인으로 인식합니다.
# 쿠키를 공유하려면 .gnuboard.com 과 같이 입력하세요.
# 이곳에 입력하지 않으면 www 붙은 도메인과 그렇지 않은 도메인은 쿠키를 공유하지 못하므로
# 로그인이 풀릴 수 있습니다.
COOKIE_DOMAIN = ""
화면이 출력되지 않으며 아래와 같은 오류 발생
File "/home/ubuntu/.local/lib/python3.10/site-packages/starlette/middleware/base.py", line 108, in __call__
response = await self.dispatch_func(request, call_next)
File "/home/ubuntu/gnu6/main.py", line 129, in main_middleware
return template_response("alert.html", context, e.status_code)
File "/home/ubuntu/gnu6/core/exception.py", line 73, in template_response
return template.TemplateResponse(template_html, context, status_code)
File "/home/ubuntu/.local/lib/python3.10/site-packages/starlette/templating.py", line 110, in TemplateResponse
context.update(context_processor(request))
File "/home/ubuntu/gnu6/core/template.py", line 87, in _default_context
"menus": get_menus(),
File "/home/ubuntu/gnu6/lib/common.py", line 1305, in get_menus
parent_menus = db.scalars(
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/orm/session.py", line 2420, in scalars
return self._execute_internal(
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/orm/session.py", line 2190, in _execute_internal
result: Result[Any] = compile_state_cls.orm_execute_statement(
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/orm/context.py", line 293, in orm_execute_statement
result = conn.execute(
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/engine/base.py", line 1416, in execute
return meth(
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/sql/elements.py", line 516, in _execute_on_connection
return connection._execute_clauseelement(
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/engine/base.py", line 1639, in _execute_clauseelement
ret = self._execute_context(
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/engine/base.py", line 1848, in _execute_context
return self._exec_single_context(
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/engine/base.py", line 1988, in _exec_single_context
self._handle_dbapi_exception(
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/engine/base.py", line 2343, in _handle_dbapi_exception
raise sqlalchemy_exception.with_traceback(exc_info[2]) from e
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/engine/base.py", line 1969, in _exec_single_context
self.dialect.do_execute(
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/engine/default.py", line 922, in do_execute
cursor.execute(statement, parameters)
sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such table: g6_menu
[SQL: SELECT g6_menu.me_id, g6_menu.me_code, g6_menu.me_name, g6_menu.me_link, g6_menu.me_target, g6_menu.me_order, g6_menu.me_use, g6_menu.me_mobile_use
FROM g6_menu
WHERE length(g6_menu.me_code) = ? ORDER BY g6_menu.me_order]
[parameters: (2,)]
(Background on this error at: https://sqlalche.me/e/20/e3q8)
admin/templates/base.html
Copyright © 49.247.41.166. All rights reserved. Version 5.5.8.3.4<br>
base.html
<html>
<head>
<title>제목</title>
<script></script>
</head>
<body>
{% block content %}
{% endblock content %}
</body>
</html>
base.html
{% extends "base_body.html" %}
{% block content %}
{% endblock content %}
base_body.html
{% extends "base_head.html" %}
{% block base_body %}
<!-- layout -->
{% endblock base_body %}
base_head.html
<html>
<head>
<title>제목</title>
<script></script>
</head>
<body>
{% block base_body %}
{% block content %}
{% endblock content %}
{% endblock base_body %}
</body>
</html>
memo_list.html
{% extends "base_head.html" %}
{% import "/sideview/macros.html" as sideview %}
{% block title %}내 쪽지함{% endblock title %}
{% block content %}
<!-- 컨텐츠 -->
{% endblock content %}
테마 관련해서 작업한 분이 누굴까요?
오래전에 얘기를 한다는게 까먹고 있었네요. ㅠ
me_read_datetime = Column(DateTime, nullable=True)
sqlalchemy.exc.IntegrityError: (pymysql.err.IntegrityError) (1048, "Column 'me_read_datetime' cannot be null")
Annotated 클래스는 파이썬 타입 힌트와 FastAPI의 의존성 주입 시스템을 세밀하게 제어하기 위한 도구입니다.
Annotated을 사용하면 더 많은 정보를 타입 힌트에 추가하고 FastAPI가 이 정보를 활용하도록 할 수 있습니다.
1. 기본값 선언이 더 직관적이다.
# Before
kind: str = Query(default="recv"),
# After
kind: Annotated[str, Query()] = "recv",
2. 중복코드량 감소
# 데이터베이스 의존성 주입
DBSession = Annotated[Session, Depends(get_db)]
@router.post("/memo_form_update")
async def memo_form_update(
request: Request,
db: DBSession,
...
3. parmater 순서에 대한 제한이 없음
4. 의존성주입을 세부적으로 커스터마이징 가능
5. API 문서화
브랜치 : https://github.com/gnuboard/gnu6/tree/split-html
File "/home/ubuntu/.local/lib/python3.10/site-packages/jinja2/environment.py", line 936, in handle_exception
raise rewrite_traceback_stack(source=source)
File "templates/basic/alert.html", line 1, in top-level template code
{% extends "base_head.html" %}
File "templates/basic/base_head.html", line 11, in top-level template code
<link rel="stylesheet" href="{{ theme_asset('css/board.css') }}">
File "/home/ubuntu/.local/lib/python3.10/site-packages/jinja2/utils.py", line 83, in from_obj
if hasattr(obj, "jinja_pass_arg"):
jinja2.exceptions.UndefinedError: 'theme_asset' is undefined
글쓰기, 쪽지 보내기시 오류 발행
업무분장은 @KimTom89 이 하세요.
그누보드5 버전과 같이 웹브라우저에서 설치하는 기능 추가
DB 선택
MySQL 선택시 HOST, PORT, USER, PASSWORD, DB NAME 설정
PostgreSQL 선택시 ???
관리자 아이디, 패스워드 등 설정
재설치 여부
jinja 템플릿 캐시로 인해 템플릿이름이 동일한 경우 바뀌지 않습니다.
basic 테마 index.html -> test 템플릿 로딩 index.html -> basic index.html
env.loader.searchpath 변경시에도 basic index.html 계속로딩
변경시 캐시삭제
Traceback (most recent call last):
File "/home/ubuntu/.local/lib/python3.10/site-packages/uvicorn/protocols/http/httptools_impl.py", line 426, in run_asgi
result = await app( # type: ignore[func-returns-value]
File "/home/ubuntu/.local/lib/python3.10/site-packages/uvicorn/middleware/proxy_headers.py", line 84, in __call__
return await self.app(scope, receive, send)
File "/home/ubuntu/.local/lib/python3.10/site-packages/fastapi/applications.py", line 292, in __call__
await super().__call__(scope, receive, send)
File "/home/ubuntu/.local/lib/python3.10/site-packages/starlette/applications.py", line 122, in __call__
await self.middleware_stack(scope, receive, send)
File "/home/ubuntu/.local/lib/python3.10/site-packages/starlette/middleware/errors.py", line 184, in __call__
raise exc
File "/home/ubuntu/.local/lib/python3.10/site-packages/starlette/middleware/errors.py", line 162, in __call__
await self.app(scope, receive, _send)
File "/home/ubuntu/.local/lib/python3.10/site-packages/starlette/middleware/sessions.py", line 86, in __call__
await self.app(scope, receive, send_wrapper)
File "/home/ubuntu/.local/lib/python3.10/site-packages/starlette/middleware/base.py", line 108, in __call__
response = await self.dispatch_func(request, call_next)
File "/home/ubuntu/gnu6/main.py", line 250, in main_middleware
response: Response = await call_next(request)
File "/home/ubuntu/.local/lib/python3.10/site-packages/starlette/middleware/base.py", line 84, in call_next
raise app_exc
File "/home/ubuntu/.local/lib/python3.10/site-packages/starlette/middleware/base.py", line 70, in coro
await self.app(scope, receive_or_disconnect, send_no_error)
File "/home/ubuntu/.local/lib/python3.10/site-packages/starlette/middleware/base.py", line 108, in __call__
response = await self.dispatch_func(request, call_next)
File "/home/ubuntu/gnu6/main.py", line 109, in dispatch
return await call_next(request)
File "/home/ubuntu/.local/lib/python3.10/site-packages/starlette/middleware/base.py", line 84, in call_next
raise app_exc
File "/home/ubuntu/.local/lib/python3.10/site-packages/starlette/middleware/base.py", line 70, in coro
await self.app(scope, receive_or_disconnect, send_no_error)
File "/home/ubuntu/.local/lib/python3.10/site-packages/starlette/middleware/exceptions.py", line 79, in __call__
raise exc
File "/home/ubuntu/.local/lib/python3.10/site-packages/starlette/middleware/exceptions.py", line 68, in __call__
await self.app(scope, receive, sender)
File "/home/ubuntu/.local/lib/python3.10/site-packages/fastapi/middleware/asyncexitstack.py", line 20, in __call__
raise e
File "/home/ubuntu/.local/lib/python3.10/site-packages/fastapi/middleware/asyncexitstack.py", line 17, in __call__
await self.app(scope, receive, send)
File "/home/ubuntu/.local/lib/python3.10/site-packages/starlette/routing.py", line 718, in __call__
await route.handle(scope, receive, send)
File "/home/ubuntu/.local/lib/python3.10/site-packages/starlette/routing.py", line 276, in handle
await self.app(scope, receive, send)
File "/home/ubuntu/.local/lib/python3.10/site-packages/starlette/routing.py", line 66, in app
response = await func(request)
File "/home/ubuntu/.local/lib/python3.10/site-packages/fastapi/routing.py", line 273, in app
raw_response = await run_endpoint_function(
File "/home/ubuntu/.local/lib/python3.10/site-packages/fastapi/routing.py", line 190, in run_endpoint_function
return await dependant.call(**values)
File "/home/ubuntu/gnu6/bbs/board.py", line 864, in read_post
insert_point(request, mb_id, read_point, f"{board.bo_subject} {write.wr_id} 글읽기", board.bo_table, write.wr_id, "읽기")
File "/home/ubuntu/gnu6/lib/common.py", line 927, in insert_point
db.commit()
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/orm/session.py", line 1969, in commit
trans.commit(_to_root=True)
File "<string>", line 2, in commit
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/orm/state_changes.py", line 139, in _go
ret_value = fn(self, *arg, **kw)
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/orm/session.py", line 1256, in commit
self._prepare_impl()
File "<string>", line 2, in _prepare_impl
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/orm/state_changes.py", line 139, in _go
ret_value = fn(self, *arg, **kw)
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/orm/session.py", line 1231, in _prepare_impl
self.session.flush()
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/orm/session.py", line 4312, in flush
self._flush(objects)
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/orm/session.py", line 4447, in _flush
with util.safe_reraise():
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/util/langhelpers.py", line 146, in __exit__
raise exc_value.with_traceback(exc_tb)
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/orm/session.py", line 4408, in _flush
flush_context.execute()
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/orm/unitofwork.py", line 466, in execute
rec.execute(self)
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/orm/unitofwork.py", line 642, in execute
util.preloaded.orm_persistence.save_obj(
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/orm/persistence.py", line 93, in save_obj
_emit_insert_statements(
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/orm/persistence.py", line 1226, in _emit_insert_statements
result = connection.execute(
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/engine/base.py", line 1416, in execute
return meth(
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/sql/elements.py", line 516, in _execute_on_connection
return connection._execute_clauseelement(
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/engine/base.py", line 1639, in _execute_clauseelement
ret = self._execute_context(
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/engine/base.py", line 1820, in _execute_context
self._handle_dbapi_exception(
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/engine/base.py", line 2343, in _handle_dbapi_exception
raise sqlalchemy_exception.with_traceback(exc_info[2]) from e
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/engine/base.py", line 1814, in _execute_context
context = constructor(
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/engine/default.py", line 1455, in _init_compiled
l_param: List[Any] = [
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/engine/default.py", line 1456, in <listcomp>
flattened_processors[key](compiled_params[key])
File "/home/ubuntu/.local/lib/python3.10/site-packages/sqlalchemy/dialects/sqlite/base.py", line 1142, in process
raise TypeError(
sqlalchemy.exc.StatementError: (builtins.TypeError) SQLite Date type only accepts Python date objects as input.
[SQL: INSERT INTO g6_point (mb_id, po_datetime, po_content, po_point, po_use_point, po_expired, po_expire_date, po_mb_point, po_rel_table, po_rel_id, po_rel_action) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)]
[parameters: [{'po_rel_action': '읽기', 'po_rel_table': 'free', 'po_content': '자유게시판 2 글읽기', 'po_point': -1, 'po_datetime': datetime.datetime(2024, 1, 3, 10, 18, 23, 707228), 'po_expired': 1, 'po_use_point': 0, 'mb_id': 'admin', 'po_rel_id': '2', 'po_mb_point': 209, 'po_expire_date': '2024-01-03'}]]
예) 6.0.1-beta
fastapi 의 버전 표시를 참고하여 예) 와 같이 표시할까 합니다.
앞에 v 는 붙이지 않습니다.
https://github.com/tiangolo/fastapi/tags
beta 버전을 거쳐 안정화가 되었다고 하는 시기에 -beta 를 떼려고 합니다.
예) 6.1.1
다른 의견 있으면 주세요.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.