Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -169,3 +169,6 @@ cython_debug/

# PyPI configuration file
.pypirc

# Misc
.DS_Store
31 changes: 24 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,34 @@
# python.or.kr-wip

# 개발 환경 구축
## 개발 환경 구축

```
docker compose up
```
### 1. Docker compose 이용

http://localhost:8080/cms/
테스트용 계정 정보
- id: test
- password: test

test / test
```
$ docker-compose up
```
- 접속 URL: http://localhost:8080/cms/


# settings
### 2. Django runserver 이용

```
$ source .venv/bin/activate
$ cd pythonkr_backend
$ python manage.py migrate
$ python manage.py runserver
```

Tailwind CSS 작업을 위해 다른 창에서 다음을 실행
```
$ python manage.py tailwind start
```

## Django settings
- pythonkr_backend.settings # local sqlite testing
- pythonkr_backend.settings.localtesting # docker compose testing
- pythonkr_backend.settings.prod # production
3 changes: 2 additions & 1 deletion entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@ uv sync
cd /app/pythonkr_backend
export DJANGO_SETTINGS_MODULE="pythonkr_backend.settings.localtesting"
./manage.py migrate --no-input
./manage.py tailwind build
./manage.py collectstatic --clear --noinput
export DJANGO_SUPERUSER_PASSWORD=test
./manage.py createsuperuser --username test --email [email protected] --noinput
gunicorn --workers=2 \
-b :8080 \
--access-logfile - \
--error-logfile - \
pythonkr_backend.wsgi
pythonkr_backend.wsgi
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ requires-python = ">=3.12"
dependencies = [
"beautifulsoup4>=4.13.3",
"django>=5.1.7",
"django-tailwind[reload]>=3.8.0",
"gunicorn>=23.0.0",
"httpx>=0.28.1",
"llm>=0.24.2",
Expand Down
2 changes: 1 addition & 1 deletion pythonkr_backend/pythonkr/migrations/0001_initial.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class Migration(migrations.Migration):
name='PKHomePage',
fields=[
('page_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='wagtailcore.page')),
('body', wagtail.fields.RichTextField(blank=True)),
('content', wagtail.fields.RichTextField(blank=True)),
],
options={
'abstract': False,
Expand Down
8 changes: 4 additions & 4 deletions pythonkr_backend/pythonkr/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class Meta:
abstract = True

def get_context(self, request, *args, **kwargs):
"common context for PK"
"common context for Python Korea"
context = super().get_context(request, *args, **kwargs)

SponsorPageModel = apps.get_model("pythonkr", "PKSponsors")
Expand Down Expand Up @@ -81,17 +81,17 @@ def save(self, *args, **kwargs):

class PKHomePage(PKBasePage):
template = "pythonkr/pk_home.html"
body = RichTextField(blank=True)
content = RichTextField(blank=True)

subpage_types = [
PKPage,
PKDocPage,
]

content_panels = Page.content_panels + [
FieldPanel("body"),
FieldPanel("content"),
]

def get_context(self, request, *args, **kwargs):
context = super().get_context(request, *args, **kwargs)
return context
return context
Binary file removed pythonkr_backend/pythonkr/static/pao/01-Main-pao.png
Binary file not shown.
Binary file removed pythonkr_backend/pythonkr/static/pao/01-Main2.png
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
140 changes: 76 additions & 64 deletions pythonkr_backend/pythonkr/templates/pythonkr/pk_base.html
Original file line number Diff line number Diff line change
@@ -1,76 +1,88 @@
{% load static %}
{% load tailwind_tags %}
{% load wagtailcore_tags %}
{% load wagtailimages_tags %}
{% wagtail_site as current_site %}

<!DOCTYPE html>
<html lang="en">
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}Python Asia{% endblock title %}</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.2/css/bootstrap.min.css">
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/alpinejs/3.13.5/cdn.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.2/js/bootstrap.bundle.min.js"></script>
<style>
html, body {
height: 100%;
margin: 0;
}
body {
padding-top: 40px;
display: flex;
flex-direction: column;
}
main {
flex: 1;
}
footer {
background-color: #f8f9fa;
margin-bottom: 20px;
}
</style>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}파이썬 한국 사용자 모임{% endblock title %}</title>
{% tailwind_css %}
</head>
<body>
<!-- Navigation -->
<nav class="navbar navbar-expand-lg navbar-light bg-light fixed-top">
<div class="container">
<a class="navbar-brand" href="{% pageurl current_site.root_page %}">
<img src="{% static 'pao/01-Main2.png' %}" alt="Python Asia Organization Logo"
height="80"/>
</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav ms-auto">
{% for menu_page in current_site.root_page.get_children.live.in_menu %}
<li class="nav-item"><a class="nav-link" href="{% pageurl menu_page %}">{{menu_page.title}}</a></li>
{% endfor %}
</ul>
</div>
<body class="bg-white min-h-screen flex flex-col">
<!-- 내비게이션 -->
<nav class="bg-white border-b">
<div class="container mx-auto px-4">
<div class="flex justify-between items-center py-4">
<!-- 로고 + 텍스트 타이틀 -->
<div class="flex flex-row items-center space-x-4 w-auto">
<a class="navbar-brand" href="{% pageurl current_site.root_page %}">
<img class="h-12 mx-auto md:mx-0" src="{% static 'pythonkr/pythonkr-badge.png' %}" alt="Python Korea Logo"/>
</a>
<h1 class="text-xl font-bold text-gray-800 mt-2 md:mt-0 text-center md:text-left">
파이썬 한국 사용자 모임
</h1>
</div>
<!-- 내비게이션 -->
<div class="hidden md:flex space-x-4">
{% for menu_page in current_site.root_page.get_children.live.in_menu %}
<a class="text-gray-600 hover:text-gray-800" href="{% pageurl menu_page %}">{{ menu_page.title }}</a>
{% endfor %}
</div>
<!-- 모바일 메뉴 버튼 -->
<div class="md:hidden">
<button id="mobile-menu-button" class="text-gray-600 focus:outline-none">
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M4 6h16M4 12h16M4 18h16"></path>
</svg>
</button>
Comment on lines +36 to +42
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Improve mobile menu accessibility.

The mobile menu button lacks accessibility attributes for screen readers.

Add ARIA attributes for better accessibility:

-<button id="mobile-menu-button" class="text-gray-600 focus:outline-none">
+<button id="mobile-menu-button" 
+        class="text-gray-600 focus:outline-none"
+        aria-label="메뉴 열기"
+        aria-expanded="false"
+        aria-controls="mobile-menu">

Also update the JavaScript to manage the aria-expanded attribute:

 mobileMenuButton.addEventListener('click', () => {
+    const isExpanded = !mobileMenu.classList.contains('hidden');
     mobileMenu.classList.toggle('hidden');
+    mobileMenuButton.setAttribute('aria-expanded', isExpanded.toString());
 });
🤖 Prompt for AI Agents
In pythonkr_backend/pythonkr/templates/pythonkr/pk_base.html around lines 36 to
42, the mobile menu button lacks ARIA attributes needed for screen reader
accessibility. Add aria-label="Toggle menu" and aria-expanded="false" attributes
to the button element. Then update the JavaScript controlling the button to
toggle the aria-expanded attribute between "true" and "false" when the menu is
opened or closed to reflect the current state.

</div>
</nav>
</div>
</div>
<!-- 모바일 메뉴 -->
<div id="mobile-menu" class="hidden md:hidden px-4 pb-4">
{% for menu_page in current_site.root_page.get_children.live.in_menu %}
<a class="block py-2 text-gray-600 hover:bg-gray-200" href="{% pageurl menu_page %}">{{ menu_page.title }}</a>
{% endfor %}
</div>
</nav>

<!-- Main Content -->
<main class="container mt-5 pt-5">
{% block content %}{% endblock content %}
</main>
<!-- 메인 -->
<main class="flex-grow container mx-auto px-4 py-8">
<div class="prose">
{% block content %}{{ page.content|richtext }}{% endblock %}
</div>
</main>

<!-- Footer -->
<footer class="sponsor-footer mt-5">
<div class="container text-center">
<h4 class="text-center mb-4">Our Sponsors</h4>
<div class="row justify-content-center">
{% for sponsor in sponsors %}
<div class="col-md-3 col-6 text-center mb-3">
<img src="{{ sponsor.logo }}" alt="{{ sponsor.name }}" class="img-fluid" style="max-height: 60px;">
</div>
{% endfor %}
</div>
<!-- 푸터 -->
<footer class="bg-white border-t">
<div class="container mx-auto px-4 py-8">
<div class="flex flex-col md:flex-row justify-between items-start md:items-center space-y-4 md:space-y-0">
<!-- 로고 및 설명 -->
<div>
<h2 class="text-lg font-semibold text-gray-800">Python Korea</h2>
<p class="text-sm text-gray-500 mt-1">
파이썬 한국 사용자 모임은 파이썬을 사용하는 모든 사람들을 위한 열린 커뮤니티입니다.
</p>
<p class="mt-6 pt-4 text-sm text-gray-400">
© 2025 Python Korea. All rights reserved.
</p>
</div>
{% if looking_for_sponsors %}
<h4 class="text-center mb-4">looking for sponsors!</h4>
{% endif %}
</footer>
</div>
</div>
</footer>

<script>
const mobileMenuButton = document.getElementById('mobile-menu-button');
const mobileMenu = document.getElementById('mobile-menu');
mobileMenuButton.addEventListener('click', () => {
mobileMenu.classList.toggle('hidden');
});
</script>
</body>
</html>
</html>

6 changes: 0 additions & 6 deletions pythonkr_backend/pythonkr/templates/pythonkr/pk_home.html
Original file line number Diff line number Diff line change
@@ -1,8 +1,2 @@
{% extends 'pythonkr/pk_base.html' %}
{% load wagtailcore_tags %}

{% block title %}Home - Python Asia - {{ page.title }}{% endblock %}

{% block content %}
{{ page.body|richtext }}
{% endblock %}
6 changes: 0 additions & 6 deletions pythonkr_backend/pythonkr/templates/pythonkr/pk_page.html
Original file line number Diff line number Diff line change
@@ -1,8 +1,2 @@
{% extends 'pythonkr/pk_base.html' %}
{% load wagtailcore_tags %}

{% block title %}Home - Python Asia - {{ page.title }}{% endblock %}

{% block content %}
{{ page.body|richtext }}
{% endblock %}
11 changes: 11 additions & 0 deletions pythonkr_backend/pythonkr_backend/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@
"taggit",
"bakery",
"wagtailbakery",
"tailwind",
"theme",
"django_browser_reload",
"pythonkr",
"curation",
]
Expand All @@ -67,6 +70,7 @@
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'wagtail.contrib.redirects.middleware.RedirectMiddleware',
'django_browser_reload.middleware.BrowserReloadMiddleware',
]

ROOT_URLCONF = 'pythonkr_backend.urls'
Expand Down Expand Up @@ -170,3 +174,10 @@
BAKERY_VIEWS = (
"wagtailbakery.views.AllPublishedPagesView",
)

TAILWIND_APP_NAME = 'theme'

INTERNAL_IPS = [
"127.0.0.1",
"0.0.0.0",
]
3 changes: 2 additions & 1 deletion pythonkr_backend/pythonkr_backend/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@
path("admin/", admin.site.urls),
path("cms/", include(wagtailadmin_urls)),
path("documents/", include(wagtaildocs_urls)),
path("__reload__/", include("django_browser_reload.urls")),
path("", include(wagtail_urls)),
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)

urlpatterns += static(settings.MEDIA_URL + 'images/', document_root=os.path.join(settings.MEDIA_ROOT, 'images'))
urlpatterns += static(settings.MEDIA_URL + 'images/', document_root=os.path.join(settings.MEDIA_ROOT, 'images'))
Empty file.
5 changes: 5 additions & 0 deletions pythonkr_backend/theme/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from django.apps import AppConfig


class ThemeConfig(AppConfig):
name = 'theme'
1 change: 1 addition & 0 deletions pythonkr_backend/theme/static_src/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules
Loading