Compare commits

..

28 Commits

Author SHA1 Message Date
Kai
ee6c8e8253 feat: add CLAUDE.md for comprehensive development guidance, including commands, architecture overview, and deployment details
All checks were successful
test / build (push) Successful in 1m12s
test / deploy (push) Successful in 2s
2025-11-28 19:12:02 +08:00
Kai
5b387cffd9 fix: correct command syntax in test.yaml by replacing 'docker compose' with 'docker-compose' for proper deployment execution
All checks were successful
test / build (push) Successful in 4s
test / deploy (push) Successful in 3s
2025-03-25 21:57:02 +08:00
Kai
8a11774d98 chore: switch runner type in test.yaml from ubuntu-latest to self-hosted for both build and deploy jobs
Some checks failed
test / build (push) Successful in 4s
test / deploy (push) Failing after 0s
2025-03-25 15:58:20 +08:00
Kai
ac88526613 chore: restore deployment command in test.yaml and comment out echo statement for cleaner workflow
Some checks failed
test / build (push) Successful in 8s
test / deploy (push) Failing after 3s
2025-03-25 15:20:25 +08:00
Kai
5fe3ab01b4 chore: update echo statement in test.yaml for debugging clarity during deployment
All checks were successful
test / build (push) Successful in 16s
test / deploy (push) Successful in 3s
2025-03-25 15:12:42 +08:00
Kai
e03d33ff83 chore: comment out deployment command in test.yaml and add echo statement for debugging purposes
All checks were successful
test / build (push) Successful in 11s
test / deploy (push) Successful in 3s
2025-03-25 15:11:27 +08:00
Kai
d0624ea0b3 feat: add custom list method to AreaViewSet for testing purposes
All checks were successful
test / build (push) Successful in 23s
test / deploy (push) Successful in 3s
2025-03-25 15:04:14 +08:00
Kai
ef578a697b refactor: clean up code formatting in various files for improved readability
All checks were successful
test / build (push) Successful in 7s
test / deploy (push) Successful in 2s
2025-03-24 20:03:17 +08:00
Kai
4dad99ec39 chore: switch runner type in test.yaml from self-hosted to ubuntu-latest for build and deploy jobs
All checks were successful
test / build (push) Successful in 6s
test / deploy (push) Successful in 2s
2025-03-24 19:21:38 +08:00
Kai
c092044954 chore: add debug steps to test.yaml to display current directory, Node PATH, and Node version for improved troubleshooting
Some checks failed
test / build (push) Failing after 0s
test / deploy (push) Has been skipped
2025-03-24 18:58:42 +08:00
Kai
0677c36d13 chore: remove debug steps from test.yaml to streamline workflow and reduce clutter
Some checks failed
test / build (push) Failing after 0s
test / deploy (push) Has been skipped
2025-03-24 18:33:27 +08:00
Kai
d8b0439057 chore: add debug steps to test.yaml to display current directory and system information for enhanced troubleshooting
Some checks failed
test / build (push) Failing after 0s
test / deploy (push) Has been skipped
2025-03-24 18:11:18 +08:00
Kai
24222b0b41 chore: change runner type in test.yaml from ubuntu-latest to self-hosted for build and deploy jobs
Some checks failed
test / build (push) Failing after 1s
test / deploy (push) Has been skipped
2025-03-24 17:59:49 +08:00
Kai
29404d88c9 fix: correct deployment command in test.yaml to ensure proper directory navigation
All checks were successful
test / build (push) Successful in 3s
test / deploy (push) Successful in 2s
2025-03-24 16:59:13 +08:00
Kai
b4b9cca357 chore: modify test.yaml to list contents of /opt instead of /opt/docker for better visibility
Some checks failed
test / build (push) Successful in 3s
test / deploy (push) Failing after 1s
2025-03-24 16:58:06 +08:00
Kai
3982d1961f chore: add lscpu command to test.yaml for enhanced system information during debugging
Some checks failed
test / build (push) Successful in 4s
test / deploy (push) Failing after 1s
2025-03-24 16:56:53 +08:00
Kai
b1ed9c687b chore: add debug steps to test.yaml for improved troubleshooting
Some checks failed
test / build (push) Successful in 6s
test / deploy (push) Failing after 1s
2025-03-24 14:25:06 +08:00
Kai
d37219bb6c fix: update test.yaml to change deployment command for clarity
Some checks failed
test / build (push) Successful in 4s
test / deploy (push) Failing after 1s
2025-03-24 14:17:23 +08:00
Kai
95515754cc chore: update .dockerignore to include Pipfile and Pipfile.lock, add cryptography to requirements.txt, and modify compose-test.yaml for port mapping and volume path
Some checks failed
test / build (push) Successful in 5s
test / deploy (push) Failing after 2s
2025-03-24 13:58:19 +08:00
Kai
25f86068d0 fix: simplify path for requirements.txt in Dockerfile
Some checks failed
test / build (push) Successful in 3s
test / deploy (push) Failing after 1s
2025-03-24 11:55:01 +08:00
Kai
c3fe99245c fix: update Dockerfile to use the correct path for requirements.txt
Some checks failed
test / build (push) Successful in 3s
test / deploy (push) Failing after 1s
2025-03-24 11:52:57 +08:00
Kai
1d6d4ead0b fix: update Dockerfile to use COPY instead of ADD for requirements.txt
Some checks failed
test / build (push) Successful in 3s
test / deploy (push) Failing after 1s
2025-03-24 11:52:06 +08:00
Kai
228164fd07 CI
Some checks failed
test / build (push) Successful in 4s
test / deploy (push) Failing after 1s
2025-03-24 11:47:49 +08:00
Kai
d3c0e1c58a CI
Some checks failed
test / build (push) Successful in 6s
test / deploy (push) Failing after 2s
2025-03-24 11:16:50 +08:00
Kai
06c4b47eb1 CI
Some checks failed
test / build (push) Failing after 2s
test / deploy (push) Has been skipped
2025-03-24 11:15:07 +08:00
Kai
ab81f1f86c CI
Some checks failed
test / build (push) Failing after 1m44s
test / deploy (push) Has been skipped
2025-03-24 11:03:09 +08:00
Kai
0d2b118e52 CI
Some checks failed
test / build (push) Has been cancelled
test / deploy (push) Has been cancelled
2025-03-24 09:58:22 +08:00
Kai
9ef75e4377 update: test.yaml
Some checks failed
test / build (push) Has been cancelled
test / deploy (push) Has been cancelled
2025-03-21 18:39:30 +08:00
13 changed files with 155 additions and 44 deletions

View File

@ -15,7 +15,6 @@ __pycache__/
.gitignore .gitignore
# 忽略依赖文件(除非你希望它们存在于镜像中) # 忽略依赖文件(除非你希望它们存在于镜像中)
requirements.txt
Pipfile Pipfile
Pipfile.lock Pipfile.lock

View File

@ -6,27 +6,19 @@ on:
jobs: jobs:
build: build:
runs-on: test runs-on: self-hosted
steps: steps:
- name: Checkout Code - name: Checkout Code
uses: https://git.bellacocool.com/actions/checkout@v4 uses: http://gitea.xkkxyy.com/actions/checkout@main
- name: Docker Build and Push - name: Docker Build and Push
run: | run: |
docker build -t git.bellacocool.com/jsy/epr:latest . docker build -t my-django:latest .
continue-on-error: true continue-on-error: true
deploy: deploy:
runs-on: test runs-on: self-hosted
needs: build needs: build
steps: steps:
- name: Deploy to Test - name: Deploy to Test
run: cd /opt/docker && docker compose -f docker-compose.yaml -f epr/docker-compose.yaml up -d run: cd /opt/docker && docker-compose -f docker-compose.yaml -f my-django/docker-compose.yaml up -d
release:
runs-on: test
needs: build
steps:
- name: Release Package
run: |
docker run --rm -e GITHUB_RUN_NUMBER=$GITHUB_RUN_NUMBER git.bellacocool.com/jsy/epr sh release.sh

115
CLAUDE.md Normal file
View File

@ -0,0 +1,115 @@
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Development Commands
### Running the Application
```bash
# Start development server (for local development)
python manage.py runserver
# Start with uvicorn (production-like)
uvicorn mysite.asgi:application --host=0.0.0.0 --port=8000 --reload
```
### Database Operations
```bash
# Run migrations
python manage.py makemigrations
python manage.py migrate
# Create superuser
python manage.py createsuperuser
```
### Docker Development
```bash
# Build Docker image
docker build -t my-django:latest .
# Run with Docker Compose (see deploy/compose-test.yaml)
docker-compose -f deploy/compose-test.yaml up -d
```
### Testing
```bash
# Run tests
python manage.py test
# Run tests for specific app
python manage.py test apps.role
```
## Architecture Overview
### Project Structure
This is a Django 5.1 REST API project with the following key components:
- **mysite/**: Main Django project configuration
- **apps/**: Modular Django applications
- `area/`: Geographic area management
- `dictionary/`: Data dictionary/configuration
- `menu/`: Navigation menu system
- `menu_button/`: Menu button permissions
- `role/`: Role-based access control
- `system_user/`: User management
- **utils/**: Shared utilities and middleware
### Key Configuration Details
#### Database Setup
- **Primary Database**: MySQL (host: 47.108.232.131:3306, database: ky)
- **Secondary Database**: MongoDB (host: 47.108.232.131:27017, database: wk)
- **Caching**: Redis with multiple databases (0: default, 1: queue, 2: base, 3: cache)
#### REST Framework Configuration
- Uses Django REST Framework 3.15.2
- JSON response format with custom response wrapper
- Exception handling via `utils.exception.CustomExceptionMiddleware`
- Filtering support via django-filter
- API documentation with CoreAPI
#### Internationalization
- Primary language: Chinese (zh-hans)
- Timezone: Asia/Shanghai
- Localization support enabled
### API Structure
All APIs follow the pattern:
- `/area/` - Area management endpoints
- `/role/` - Role management endpoints
- `/menu/` - Menu management endpoints
- `/menu_button/` - Menu button endpoints
- `/dictionary/` - Dictionary endpoints
- `/system_user/` - User management endpoints
### Custom Utilities
- `utils.json_response.Response`: Standardized API response wrapper
- `utils.exception.CustomExceptionMiddleware`: Global exception handling
- `utils.paginator`: Custom pagination logic
- `utils.redis`: Redis connection utilities
### Deployment
- Containerized with Docker (Python 3.11-slim base)
- Uses uvicorn ASGI server
- CI/CD via GitHub Actions with self-hosted runners
- Deployment to test environment via Docker Compose
## Development Notes
### Dependencies
- Core: Django 5.1.5, Django REST Framework 3.15.2
- Database: PyMySQL, mongoengine
- Caching: django-redis
- Server: uvicorn
### Security Considerations
- CSRF middleware is disabled (line 55 in settings.py)
- Custom exception middleware catches all unhandled exceptions
- Debug mode enabled (should be disabled in production)
### Logging
- Comprehensive logging setup with rotation
- Separate log files for general logs and error logs
- File-based logging with console output for development

View File

@ -2,7 +2,7 @@ FROM python:3.11-slim
WORKDIR /opt/my-django WORKDIR /opt/my-django
ADD requirements.txt requirements.txt COPY requirements.txt .
RUN pip install --upgrade pip && pip install -r requirements.txt --timeout=1000 -i https://mirrors.cloud.tencent.com/pypi/simple RUN pip install --upgrade pip && pip install -r requirements.txt --timeout=1000 -i https://mirrors.cloud.tencent.com/pypi/simple

View File

@ -1,5 +1,7 @@
# Create your views here. # Create your views here.
from rest_framework import viewsets from rest_framework import viewsets
from utils.json_response import Response
from .models import Area from .models import Area
from .serializers import AreaSerializer from .serializers import AreaSerializer
from utils.paginator import BasicSetPagination from utils.paginator import BasicSetPagination
@ -8,9 +10,7 @@ from django_filters import rest_framework
class AreaFilter(rest_framework.FilterSet): class AreaFilter(rest_framework.FilterSet):
level = rest_framework.NumberFilter(field_name="level", lookup_expr="exact") level = rest_framework.NumberFilter(field_name="level", lookup_expr="exact")
parent_code = rest_framework.CharFilter( parent_code = rest_framework.CharFilter(field_name="parent_code", lookup_expr="exact")
field_name="parent_code", lookup_expr="exact"
)
class Meta: class Meta:
model = Area model = Area
@ -25,3 +25,6 @@ class AreaViewSet(viewsets.ModelViewSet):
rest_framework.DjangoFilterBackend, rest_framework.DjangoFilterBackend,
] # 过滤器 ] # 过滤器
filterset_class = AreaFilter filterset_class = AreaFilter
def list(self, request):
return Response("test")

View File

@ -1,6 +1,7 @@
from rest_framework import serializers from rest_framework import serializers
from .models import Menu from .models import Menu
class MenuSerializer(serializers.ModelSerializer): class MenuSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = Menu model = Menu

View File

@ -19,9 +19,7 @@ class MenuButton(BaseModel):
(2, "PUT"), (2, "PUT"),
(3, "DELETE"), (3, "DELETE"),
] ]
method = models.IntegerField( method = models.IntegerField(choices=METHOD_CHOICES, default=0, verbose_name="接口请求方式")
choices=METHOD_CHOICES, default=0, verbose_name="接口请求方式"
)
status = models.BooleanField(default=True, verbose_name="状态") status = models.BooleanField(default=True, verbose_name="状态")
class Meta: class Meta:

View File

@ -1,6 +1,7 @@
from rest_framework import serializers from rest_framework import serializers
from .models import Role from .models import Role
class RoleSerializer(serializers.ModelSerializer): class RoleSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = Role model = Role

14
deploy/compose-test.yaml Normal file
View File

@ -0,0 +1,14 @@
services:
my-django:
image: my-django:latest
command: ["uvicorn", "mysite.asgi:application", "--host=0.0.0.0", "--port=80", "--reload"]
ports:
- 8080:80
deploy:
mode: replicated
replicas: 1
environment:
env: test
restart: unless-stopped
volumes:
- ../../my-django:/opt/my-django

View File

@ -190,9 +190,7 @@ connect(db="wk", host="47.108.232.131", port=27017, username="wk", password="moo
# rest_framework配置 # rest_framework配置
REST_FRAMEWORK = { REST_FRAMEWORK = {
"DATETIME_FORMAT": "%Y-%m-%d %H:%M:%S", # 时间格式 "DATETIME_FORMAT": "%Y-%m-%d %H:%M:%S", # 时间格式
"DEFAULT_FILTER_BACKENDS": ( "DEFAULT_FILTER_BACKENDS": ("django_filters.rest_framework.DjangoFilterBackend",), # 过滤器
"django_filters.rest_framework.DjangoFilterBackend", # 过滤器
),
"DEFAULT_SCHEMA_CLASS": "rest_framework.schemas.coreapi.AutoSchema", # 自动生成api文档 "DEFAULT_SCHEMA_CLASS": "rest_framework.schemas.coreapi.AutoSchema", # 自动生成api文档
"DEFAULT_RENDERER_CLASSES": ( "DEFAULT_RENDERER_CLASSES": (
"rest_framework.renderers.JSONRenderer", # 返回json格式 "rest_framework.renderers.JSONRenderer", # 返回json格式
@ -209,12 +207,8 @@ if not os.path.exists(os.path.join(BASE_DIR, "logs")):
# 格式:[2020-04-22 23:33:01][micoservice.apps.ready():16] [INFO] 这是一条日志: # 格式:[2020-04-22 23:33:01][micoservice.apps.ready():16] [INFO] 这是一条日志:
# 格式:[日期][模块.函数名称():行号] [级别] 信息 # 格式:[日期][模块.函数名称():行号] [级别] 信息
STANDARD_LOG_FORMAT = ( STANDARD_LOG_FORMAT = "[%(asctime)s][%(name)s.%(funcName)s():%(lineno)d] [%(levelname)s] %(message)s"
"[%(asctime)s][%(name)s.%(funcName)s():%(lineno)d] [%(levelname)s] %(message)s" CONSOLE_LOG_FORMAT = "[%(asctime)s][%(name)s.%(funcName)s():%(lineno)d] [%(levelname)s] %(message)s"
)
CONSOLE_LOG_FORMAT = (
"[%(asctime)s][%(name)s.%(funcName)s():%(lineno)d] [%(levelname)s] %(message)s"
)
LOGGING = { LOGGING = {
"version": 1, "version": 1,
"disable_existing_loggers": False, "disable_existing_loggers": False,

View File

@ -1,3 +1,5 @@
uvicorn
cryptography
Django~=5.1.5 Django~=5.1.5
djangorestframework~=3.15.2 djangorestframework~=3.15.2
django-filter~=25.1 django-filter~=25.1

View File

@ -13,9 +13,7 @@ class BaseModel(models.Model):
""" """
id = models.BigAutoField(primary_key=True, verbose_name="Id", help_text="主键id") id = models.BigAutoField(primary_key=True, verbose_name="Id", help_text="主键id")
description = models.TextField( description = models.TextField(null=True, blank=True, verbose_name="描述", help_text="描述")
null=True, blank=True, verbose_name="描述", help_text="描述"
)
created_at = models.DateTimeField(auto_now_add=True, verbose_name="创建时间") created_at = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
updated_at = models.DateTimeField(auto_now=True, verbose_name="更新时间") updated_at = models.DateTimeField(auto_now=True, verbose_name="更新时间")
is_deleted = models.BooleanField(default=False, verbose_name="是否删除") is_deleted = models.BooleanField(default=False, verbose_name="是否删除")
@ -40,11 +38,7 @@ class BaseModel(models.Model):
] ]
def get_need_fields_names(self): def get_need_fields_names(self):
return [ return [field.name for field in self.get_all_fields() if field.name not in self.exclude_fields]
field.name
for field in self.get_all_fields()
if field.name not in self.exclude_fields
]
def to_dict_data(self): def to_dict_data(self):
""" """
@ -60,9 +54,7 @@ class BaseModel(models.Model):
""" """
插入模型 插入模型
""" """
assert ( assert self.pk is None, f"模型{self.__class__.__name__}还没有保存到数据中不能手动指定ID"
self.pk is None
), f"模型{self.__class__.__name__}还没有保存到数据中不能手动指定ID"
return self.__class__._default_manager.create(**self.DICT_DATA) return self.__class__._default_manager.create(**self.DICT_DATA)
def update(self, request, update_data: dict[str, any] = None): def update(self, request, update_data: dict[str, any] = None):