feat: add student list view with attendance statistics and configure project gitignore

This commit is contained in:
Xiao Furen 2026-08-03 22:57:38 +08:00
parent b8f2bbbadf
commit 994f4db5e1
3 changed files with 244 additions and 243 deletions

410
.gitignore vendored
View file

@ -1,206 +1,206 @@
# Byte-compiled / optimized / DLL files # Byte-compiled / optimized / DLL files
__pycache__/ __pycache__/
*.py[codz] *.py[codz]
*$py.class *$py.class
# C extensions # C extensions
*.so *.so
# Distribution / packaging # Distribution / packaging
.Python .Python
build/ build/
develop-eggs/ develop-eggs/
dist/ dist/
downloads/ downloads/
eggs/ eggs/
.eggs/ .eggs/
lib/ lib/
lib64/ lib64/
parts/ parts/
sdist/ sdist/
var/ var/
wheels/ wheels/
share/python-wheels/ share/python-wheels/
*.egg-info/ *.egg-info/
.installed.cfg .installed.cfg
*.egg *.egg
MANIFEST MANIFEST
# PyInstaller # PyInstaller
# Usually these files are written by a python script from a template # Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it. # before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest *.manifest
*.spec *.spec
# Installer logs # Installer logs
pip-log.txt pip-log.txt
pip-delete-this-directory.txt pip-delete-this-directory.txt
# Unit test / coverage reports # Unit test / coverage reports
htmlcov/ htmlcov/
.tox/ .tox/
.nox/ .nox/
.coverage .coverage
.coverage.* .coverage.*
.cache .cache
nosetests.xml nosetests.xml
coverage.xml coverage.xml
*.cover *.cover
*.py.cover *.py.cover
.hypothesis/ .hypothesis/
.pytest_cache/ .pytest_cache/
cover/ cover/
# Translations # Translations
*.mo *.mo
*.pot *.pot
# Django stuff: # Django stuff:
*.log *.log
local_settings.py local_settings.py
db.sqlite3 db.sqlite3
db.sqlite3-journal db.sqlite3-journal
# Flask stuff: # Flask stuff:
instance/ instance/
.webassets-cache .webassets-cache
# Scrapy stuff: # Scrapy stuff:
.scrapy .scrapy
# Sphinx documentation # Sphinx documentation
docs/_build/ docs/_build/
# PyBuilder # PyBuilder
.pybuilder/ .pybuilder/
target/ target/
# Jupyter Notebook # Jupyter Notebook
.ipynb_checkpoints .ipynb_checkpoints
# IPython # IPython
profile_default/ profile_default/
ipython_config.py ipython_config.py
# pyenv # pyenv
# For a library or package, you might want to ignore these files since the code is # For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in: # intended to run in multiple environments; otherwise, check them in:
# .python-version # .python-version
# pipenv # pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies # However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not # having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies. # install all needed dependencies.
#Pipfile.lock #Pipfile.lock
# UV # UV
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control. # Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more # This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries. # commonly ignored for libraries.
#uv.lock #uv.lock
# poetry # poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more # This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries. # commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock #poetry.lock
#poetry.toml #poetry.toml
# pdm # pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
# pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python. # pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
# https://pdm-project.org/en/latest/usage/project/#working-with-version-control # https://pdm-project.org/en/latest/usage/project/#working-with-version-control
#pdm.lock #pdm.lock
#pdm.toml #pdm.toml
.pdm-python .pdm-python
.pdm-build/ .pdm-build/
# pixi # pixi
# Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control. # Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
#pixi.lock #pixi.lock
# Pixi creates a virtual environment in the .pixi directory, just like venv module creates one # Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
# in the .venv directory. It is recommended not to include this directory in version control. # in the .venv directory. It is recommended not to include this directory in version control.
.pixi .pixi
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/ __pypackages__/
# Celery stuff # Celery stuff
celerybeat-schedule celerybeat-schedule
celerybeat.pid celerybeat.pid
# SageMath parsed files # SageMath parsed files
*.sage.py *.sage.py
# Environments # Environments
.env .env
.envrc .envrc
.venv .venv
env/ env/
venv/ venv/
ENV/ ENV/
env.bak/ env.bak/
venv.bak/ venv.bak/
# Spyder project settings # Spyder project settings
.spyderproject .spyderproject
.spyproject .spyproject
# Rope project settings # Rope project settings
.ropeproject .ropeproject
# mkdocs documentation # mkdocs documentation
/site /site
# mypy # mypy
.mypy_cache/ .mypy_cache/
.dmypy.json .dmypy.json
dmypy.json dmypy.json
# Pyre type checker # Pyre type checker
.pyre/ .pyre/
# pytype static type analyzer # pytype static type analyzer
.pytype/ .pytype/
# Cython debug symbols # Cython debug symbols
cython_debug/ cython_debug/
# PyCharm # PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear # and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder. # option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/ #.idea/
# Abstra # Abstra
# Abstra is an AI-powered process automation framework. # Abstra is an AI-powered process automation framework.
# Ignore directories containing user credentials, local state, and settings. # Ignore directories containing user credentials, local state, and settings.
# Learn more at https://abstra.io/docs # Learn more at https://abstra.io/docs
.abstra/ .abstra/
# Visual Studio Code # Visual Studio Code
# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore # Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
# that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore # that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
# and can be added to the global gitignore or merged into this file. However, if you prefer, # and can be added to the global gitignore or merged into this file. However, if you prefer,
# you could uncomment the following to ignore the entire vscode folder # you could uncomment the following to ignore the entire vscode folder
# .vscode/ # .vscode/
# Ruff stuff: # Ruff stuff:
.ruff_cache/ .ruff_cache/
# PyPI configuration file # PyPI configuration file
.pypirc .pypirc
# Marimo # Marimo
marimo/_static/ marimo/_static/
marimo/_lsp/ marimo/_lsp/
__marimo__/ __marimo__/
# Streamlit # Streamlit
.streamlit/secrets.toml .streamlit/secrets.toml
######### #########
db.sqlite3.* db.sqlite3.*

View file

@ -1,36 +1,36 @@
<!-- 在 templates/students/student_list.html --> <!-- 在 templates/students/student_list.html -->
{% extends 'base.html' %} {% extends 'base.html' %}
{% block title %}學生列表{% endblock %} {% block title %}學生列表{% endblock %}
{% block content %} {% block content %}
<h1>學生列表</h1> <h1>學生列表</h1>
<table class="table table-striped"> <table class="table table-striped">
<thead> <thead>
<tr> <tr>
<th>學號</th> <th>學號</th>
<th>姓名</th> <th>姓名</th>
<th>班級</th> <th>班級</th>
<th>考勤次數</th> <th>考勤次數</th>
<th>詳細資料</th> <th>詳細資料</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for item in student_data %} {% for item in student_data %}
<tr> <tr>
<td>{{ item.student.student_id }}</td> <td>{{ item.student.student_id }}</td>
<td>{{ item.student.name }}</td> <td>{{ item.student.name }}</td>
<td>{{ item.student.grade|default:"未填" }}</td> <td>{{ item.student.grade|default:"未填" }}</td>
<td>{{ item.total_attendance }}</td> <td>{{ item.total_attendance }}</td>
<td><a href="{% url 'show_attendance' item.student.student_id %}" class="btn btn-sm btn-primary">查看詳情</a></td> <td><a href="{% url 'show_attendance' item.student.student_id %}" class="btn btn-sm btn-primary">查看詳情</a></td>
</tr> </tr>
{% empty %} {% empty %}
<tr> <tr>
<td colspan="5" class="text-center">沒有學生資料</td> <td colspan="5" class="text-center">沒有學生資料</td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>
{% endblock %} {% endblock %}

View file

@ -12,14 +12,15 @@ def record_attendance(request):
if request.method == 'POST': if request.method == 'POST':
student_ids = request.POST.getlist('student_id') student_ids = request.POST.getlist('student_id')
current_datetime = datetime.now() current_datetime = datetime.now()
one_hour_ago = current_datetime - timedelta(hours=1) # one_hour_ago = current_datetime - timedelta(hours=1)
four_hours_ago = current_datetime - timedelta(hours=4)
for student_id in student_ids: for student_id in student_ids:
try: try:
student = Student.objects.get(student_id=student_id) student = Student.objects.get(student_id=student_id)
# 檢查該學生在小時內是否有點名紀錄 # 檢查該學生在4小時內是否有點名紀錄
if not PointRecord.objects.filter(student=student, datetime__gte=one_hour_ago).exists(): if not PointRecord.objects.filter(student=student, datetime__gte=four_hours_ago).exists():
point_record = PointRecord.objects.create(student=student, datetime=current_datetime) point_record = PointRecord.objects.create(student=student, datetime=current_datetime)
point_records.append(point_record) point_records.append(point_record)
except Student.DoesNotExist: except Student.DoesNotExist: