fnschool 20250109.80500.803__py3-none-any.whl → 20251011.80531.840__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of fnschool might be problematic. Click here for more details.
- fnschoo1/__init__.py +52 -0
- fnschoo1/canteen/admin.py +3 -0
- fnschoo1/canteen/apps.py +6 -0
- fnschoo1/canteen/forms.py +84 -0
- fnschoo1/canteen/migrations/0001_initial.py +119 -0
- fnschoo1/canteen/migrations/0002_ingredient_is_disabled.py +20 -0
- fnschoo1/canteen/migrations/0003_consumption_is_disabled_alter_ingredient_is_disabled.py +23 -0
- fnschoo1/canteen/migrations/0004_alter_ingredient_name_category_and_more.py +66 -0
- fnschoo1/canteen/migrations/0005_alter_category_created_at_alter_category_name_and_more.py +41 -0
- fnschoo1/canteen/migrations/0006_category_is_disabled_alter_category_user_and_more.py +49 -0
- fnschoo1/canteen/migrations/0007_alter_consumption_amount_used_and_more.py +30 -0
- fnschoo1/canteen/migrations/0008_category_abbreviation_mealtype.py +67 -0
- fnschoo1/canteen/migrations/0009_alter_category_abbreviation_and_more.py +55 -0
- fnschoo1/canteen/migrations/0010_alter_consumption_options_alter_ingredient_options_and_more.py +215 -0
- fnschoo1/canteen/migrations/0011_category_pin_to_consumptions_top.py +23 -0
- fnschoo1/canteen/migrations/0012_alter_ingredient_storage_date.py +18 -0
- fnschoo1/canteen/models.py +179 -0
- fnschoo1/canteen/templates/canteen/category/create.html +17 -0
- fnschoo1/canteen/templates/canteen/category/delete.html +61 -0
- fnschoo1/canteen/templates/canteen/category/list.html +63 -0
- fnschoo1/canteen/templates/canteen/category/update.html +23 -0
- fnschoo1/canteen/templates/canteen/close.html +11 -0
- fnschoo1/canteen/templates/canteen/consumption/_create.html +19 -0
- fnschoo1/canteen/templates/canteen/consumption/create.html +456 -0
- fnschoo1/canteen/templates/canteen/ingredient/close.html +11 -0
- fnschoo1/canteen/templates/canteen/ingredient/create.html +19 -0
- fnschoo1/canteen/templates/canteen/ingredient/create_one.html +17 -0
- fnschoo1/canteen/templates/canteen/ingredient/delete.html +41 -0
- fnschoo1/canteen/templates/canteen/ingredient/list.html +128 -0
- fnschoo1/canteen/templates/canteen/ingredient/update.html +23 -0
- fnschoo1/canteen/templates/canteen/meal_type/create.html +17 -0
- fnschoo1/canteen/templates/canteen/meal_type/delete.html +56 -0
- fnschoo1/canteen/templates/canteen/meal_type/list.html +59 -0
- fnschoo1/canteen/templates/canteen/meal_type/update.html +23 -0
- fnschoo1/canteen/tests.py +3 -0
- fnschoo1/canteen/urls.py +116 -0
- fnschoo1/canteen/views.py +814 -0
- fnschoo1/canteen/workbook/generate.py +2098 -0
- fnschoo1/db.sqlite3 +0 -0
- fnschoo1/fnschool/__init__.py +13 -0
- fnschoo1/fnschool/asgi.py +16 -0
- fnschoo1/fnschool/settings.py +167 -0
- fnschoo1/fnschool/templatetags/fnschool_tags.py +27 -0
- fnschoo1/fnschool/urls.py +30 -0
- fnschoo1/fnschool/views.py +9 -0
- fnschoo1/fnschool/wsgi.py +16 -0
- fnschoo1/locale/en/LC_MESSAGES/django.mo +0 -0
- fnschoo1/locale/zh_Hans/LC_MESSAGES/django.mo +0 -0
- fnschoo1/manage.py +25 -0
- fnschoo1/profiles/admin.py +27 -0
- fnschoo1/profiles/apps.py +12 -0
- fnschoo1/profiles/forms.py +67 -0
- fnschoo1/profiles/migrations/0001_initial.py +192 -0
- fnschoo1/profiles/migrations/0002_alter_profile_bio.py +20 -0
- fnschoo1/profiles/migrations/0003_alter_profile_options_alter_profile_address_and_more.py +67 -0
- fnschoo1/profiles/migrations/0004_profile_gender.py +26 -0
- fnschoo1/profiles/migrations/0005_alter_profile_gender.py +23 -0
- fnschoo1/profiles/models.py +60 -0
- fnschoo1/profiles/signals.py +20 -0
- fnschoo1/profiles/templates/profiles/create.html +16 -0
- fnschoo1/profiles/templates/profiles/detail.html +14 -0
- fnschoo1/profiles/templates/profiles/edit.html +12 -0
- fnschoo1/profiles/templates/profiles/log_in.html +20 -0
- fnschoo1/profiles/templates/profiles/log_out.html +12 -0
- fnschoo1/profiles/tests.py +3 -0
- fnschoo1/profiles/urls.py +15 -0
- fnschoo1/profiles/views.py +63 -0
- fnschoo1/static/css/bootstrap.min.css +11776 -0
- fnschoo1/static/css/fnschool.css +26 -0
- fnschoo1/static/js/bootstrap.bundle.min.js +4223 -0
- fnschoo1/static/js/bootstrap.min.js +2919 -0
- fnschoo1/static/js/fnschool.js +84 -0
- fnschoo1/static/js/jquery.min.js +5413 -0
- fnschoo1/static/js/jquery.slim.min.js +4331 -0
- fnschoo1/static/js/popper.min.js +1306 -0
- fnschoo1/static_collected/admin/css/autocomplete.css +377 -0
- fnschoo1/static_collected/admin/css/base.css +1224 -0
- fnschoo1/static_collected/admin/css/changelists.css +334 -0
- fnschoo1/static_collected/admin/css/dark_mode.css +136 -0
- fnschoo1/static_collected/admin/css/dashboard.css +30 -0
- fnschoo1/static_collected/admin/css/forms.css +546 -0
- fnschoo1/static_collected/admin/css/login.css +62 -0
- fnschoo1/static_collected/admin/css/nav_sidebar.css +145 -0
- fnschoo1/static_collected/admin/css/responsive.css +1043 -0
- fnschoo1/static_collected/admin/css/responsive_rtl.css +84 -0
- fnschoo1/static_collected/admin/css/rtl.css +311 -0
- fnschoo1/static_collected/admin/css/vendor/select2/select2.css +708 -0
- fnschoo1/static_collected/admin/css/vendor/select2/select2.min.css +1 -0
- fnschoo1/static_collected/admin/css/widgets.css +639 -0
- fnschoo1/static_collected/admin/js/SelectBox.js +128 -0
- fnschoo1/static_collected/admin/js/SelectFilter2.js +503 -0
- fnschoo1/static_collected/admin/js/actions.js +232 -0
- fnschoo1/static_collected/admin/js/admin/DateTimeShortcuts.js +496 -0
- fnschoo1/static_collected/admin/js/admin/RelatedObjectLookups.js +276 -0
- fnschoo1/static_collected/admin/js/autocomplete.js +33 -0
- fnschoo1/static_collected/admin/js/calendar.js +251 -0
- fnschoo1/static_collected/admin/js/cancel.js +29 -0
- fnschoo1/static_collected/admin/js/change_form.js +21 -0
- fnschoo1/static_collected/admin/js/collapse.js +43 -0
- fnschoo1/static_collected/admin/js/core.js +174 -0
- fnschoo1/static_collected/admin/js/filters.js +37 -0
- fnschoo1/static_collected/admin/js/inlines.js +439 -0
- fnschoo1/static_collected/admin/js/jquery.init.js +8 -0
- fnschoo1/static_collected/admin/js/nav_sidebar.js +81 -0
- fnschoo1/static_collected/admin/js/popup_response.js +24 -0
- fnschoo1/static_collected/admin/js/prepopulate.js +43 -0
- fnschoo1/static_collected/admin/js/prepopulate_init.js +20 -0
- fnschoo1/static_collected/admin/js/theme.js +57 -0
- fnschoo1/static_collected/admin/js/urlify.js +529 -0
- fnschoo1/static_collected/admin/js/vendor/jquery/jquery.js +10913 -0
- fnschoo1/static_collected/admin/js/vendor/jquery/jquery.min.js +2 -0
- fnschoo1/static_collected/admin/js/vendor/select2/i18n/af.js +43 -0
- fnschoo1/static_collected/admin/js/vendor/select2/i18n/ar.js +36 -0
- fnschoo1/static_collected/admin/js/vendor/select2/i18n/az.js +33 -0
- fnschoo1/static_collected/admin/js/vendor/select2/i18n/bg.js +38 -0
- fnschoo1/static_collected/admin/js/vendor/select2/i18n/bn.js +39 -0
- fnschoo1/static_collected/admin/js/vendor/select2/i18n/bs.js +48 -0
- fnschoo1/static_collected/admin/js/vendor/select2/i18n/ca.js +41 -0
- fnschoo1/static_collected/admin/js/vendor/select2/i18n/cs.js +62 -0
- fnschoo1/static_collected/admin/js/vendor/select2/i18n/da.js +37 -0
- fnschoo1/static_collected/admin/js/vendor/select2/i18n/de.js +41 -0
- fnschoo1/static_collected/admin/js/vendor/select2/i18n/dsb.js +51 -0
- fnschoo1/static_collected/admin/js/vendor/select2/i18n/el.js +43 -0
- fnschoo1/static_collected/admin/js/vendor/select2/i18n/en.js +41 -0
- fnschoo1/static_collected/admin/js/vendor/select2/i18n/es.js +41 -0
- fnschoo1/static_collected/admin/js/vendor/select2/i18n/et.js +38 -0
- fnschoo1/static_collected/admin/js/vendor/select2/i18n/eu.js +45 -0
- fnschoo1/static_collected/admin/js/vendor/select2/i18n/fa.js +42 -0
- fnschoo1/static_collected/admin/js/vendor/select2/i18n/fi.js +42 -0
- fnschoo1/static_collected/admin/js/vendor/select2/i18n/fr.js +43 -0
- fnschoo1/static_collected/admin/js/vendor/select2/i18n/gl.js +40 -0
- fnschoo1/static_collected/admin/js/vendor/select2/i18n/he.js +44 -0
- fnschoo1/static_collected/admin/js/vendor/select2/i18n/hi.js +40 -0
- fnschoo1/static_collected/admin/js/vendor/select2/i18n/hr.js +45 -0
- fnschoo1/static_collected/admin/js/vendor/select2/i18n/hsb.js +51 -0
- fnschoo1/static_collected/admin/js/vendor/select2/i18n/hu.js +44 -0
- fnschoo1/static_collected/admin/js/vendor/select2/i18n/hy.js +40 -0
- fnschoo1/static_collected/admin/js/vendor/select2/i18n/id.js +36 -0
- fnschoo1/static_collected/admin/js/vendor/select2/i18n/is.js +37 -0
- fnschoo1/static_collected/admin/js/vendor/select2/i18n/it.js +43 -0
- fnschoo1/static_collected/admin/js/vendor/select2/i18n/ja.js +40 -0
- fnschoo1/static_collected/admin/js/vendor/select2/i18n/ka.js +42 -0
- fnschoo1/static_collected/admin/js/vendor/select2/i18n/km.js +38 -0
- fnschoo1/static_collected/admin/js/vendor/select2/i18n/ko.js +42 -0
- fnschoo1/static_collected/admin/js/vendor/select2/i18n/lt.js +45 -0
- fnschoo1/static_collected/admin/js/vendor/select2/i18n/lv.js +41 -0
- fnschoo1/static_collected/admin/js/vendor/select2/i18n/mk.js +42 -0
- fnschoo1/static_collected/admin/js/vendor/select2/i18n/ms.js +38 -0
- fnschoo1/static_collected/admin/js/vendor/select2/i18n/nb.js +38 -0
- fnschoo1/static_collected/admin/js/vendor/select2/i18n/ne.js +44 -0
- fnschoo1/static_collected/admin/js/vendor/select2/i18n/nl.js +46 -0
- fnschoo1/static_collected/admin/js/vendor/select2/i18n/pl.js +43 -0
- fnschoo1/static_collected/admin/js/vendor/select2/i18n/ps.js +41 -0
- fnschoo1/static_collected/admin/js/vendor/select2/i18n/pt-BR.js +39 -0
- fnschoo1/static_collected/admin/js/vendor/select2/i18n/pt.js +41 -0
- fnschoo1/static_collected/admin/js/vendor/select2/i18n/ro.js +43 -0
- fnschoo1/static_collected/admin/js/vendor/select2/i18n/ru.js +48 -0
- fnschoo1/static_collected/admin/js/vendor/select2/i18n/sk.js +61 -0
- fnschoo1/static_collected/admin/js/vendor/select2/i18n/sl.js +41 -0
- fnschoo1/static_collected/admin/js/vendor/select2/i18n/sq.js +43 -0
- fnschoo1/static_collected/admin/js/vendor/select2/i18n/sr-Cyrl.js +48 -0
- fnschoo1/static_collected/admin/js/vendor/select2/i18n/sr.js +48 -0
- fnschoo1/static_collected/admin/js/vendor/select2/i18n/sv.js +40 -0
- fnschoo1/static_collected/admin/js/vendor/select2/i18n/th.js +36 -0
- fnschoo1/static_collected/admin/js/vendor/select2/i18n/tk.js +36 -0
- fnschoo1/static_collected/admin/js/vendor/select2/i18n/tr.js +40 -0
- fnschoo1/static_collected/admin/js/vendor/select2/i18n/uk.js +59 -0
- fnschoo1/static_collected/admin/js/vendor/select2/i18n/vi.js +37 -0
- fnschoo1/static_collected/admin/js/vendor/select2/i18n/zh-CN.js +36 -0
- fnschoo1/static_collected/admin/js/vendor/select2/i18n/zh-TW.js +33 -0
- fnschoo1/static_collected/admin/js/vendor/select2/select2.full.js +7115 -0
- fnschoo1/static_collected/admin/js/vendor/select2/select2.full.min.js +2 -0
- fnschoo1/static_collected/admin/js/vendor/xregexp/xregexp.js +4993 -0
- fnschoo1/static_collected/admin/js/vendor/xregexp/xregexp.min.js +160 -0
- fnschoo1/static_collected/css/bootstrap.min.css +11776 -0
- fnschoo1/static_collected/css/fnschool.css +26 -0
- fnschoo1/static_collected/js/bootstrap.bundle.min.js +4223 -0
- fnschoo1/static_collected/js/bootstrap.min.js +2919 -0
- fnschoo1/static_collected/js/fnschool.js +84 -0
- fnschoo1/static_collected/js/jquery.min.js +5413 -0
- fnschoo1/static_collected/js/jquery.slim.min.js +4331 -0
- fnschoo1/static_collected/js/popper.min.js +1306 -0
- fnschoo1/templates/base/_css.html +1 -0
- fnschoo1/templates/base/_js.html +15 -0
- fnschoo1/templates/base/content.html +30 -0
- fnschoo1/templates/base/header_content_footer.html +35 -0
- fnschoo1/templates/close.html +11 -0
- fnschoo1/templates/home.html +51 -0
- fnschoo1/templates/includes/_footer.html +39 -0
- fnschoo1/templates/includes/_header.html +77 -0
- fnschoo1/templates/includes/_navigation.html +0 -0
- fnschoo1/templates/includes/_paginator.html +27 -0
- fnschoo1/templates/registration/logged_out.html +0 -0
- fnschoo1/templates/registration/login.html +0 -0
- fnschool-20251011.80531.840.dist-info/METADATA +179 -0
- fnschool-20251011.80531.840.dist-info/RECORD +207 -0
- {fnschool-20250109.80500.803.dist-info → fnschool-20251011.80531.840.dist-info}/WHEEL +1 -1
- fnschool-20251011.80531.840.dist-info/entry_points.txt +2 -0
- fnschool-20251011.80531.840.dist-info/top_level.txt +1 -0
- fnschool/__init__.py +0 -35
- fnschool/__main__.py +0 -16
- fnschool/app.py +0 -103
- fnschool/canteen/__init__.py +0 -3
- fnschool/canteen/__main__.py +0 -3
- fnschool/canteen/bill.py +0 -253
- fnschool/canteen/canteen.py +0 -1
- fnschool/canteen/canteen.toml +0 -61
- fnschool/canteen/config.py +0 -10
- fnschool/canteen/consuming.py +0 -53
- fnschool/canteen/currency.py +0 -17
- fnschool/canteen/data/bill.i18n.xlsx +0 -0
- fnschool/canteen/data/bill.xlsx +0 -0
- fnschool/canteen/data/consuming.xlsx +0 -0
- fnschool/canteen/data/purchase_list.xlsx +0 -0
- fnschool/canteen/entry.py +0 -40
- fnschool/canteen/food.py +0 -206
- fnschool/canteen/food_classes.py +0 -33
- fnschool/canteen/food_classes.toml +0 -64
- fnschool/canteen/operator.py +0 -91
- fnschool/canteen/path.py +0 -28
- fnschool/canteen/spreadsheet/base.py +0 -212
- fnschool/canteen/spreadsheet/consuming.py +0 -310
- fnschool/canteen/spreadsheet/consumingsum.py +0 -76
- fnschool/canteen/spreadsheet/cover.py +0 -64
- fnschool/canteen/spreadsheet/ctspreadsheet.py +0 -351
- fnschool/canteen/spreadsheet/food.py +0 -680
- fnschool/canteen/spreadsheet/inventory.py +0 -375
- fnschool/canteen/spreadsheet/merging.py +0 -340
- fnschool/canteen/spreadsheet/preconsuming.py +0 -329
- fnschool/canteen/spreadsheet/purchasing.py +0 -885
- fnschool/canteen/spreadsheet/purchasingsum.py +0 -110
- fnschool/canteen/spreadsheet/spreadsheet.py +0 -363
- fnschool/canteen/spreadsheet/translating.py +0 -12
- fnschool/canteen/spreadsheet/unwarehousing.py +0 -178
- fnschool/canteen/spreadsheet/unwarehousingsum.py +0 -11
- fnschool/canteen/spreadsheet/warehousing.py +0 -360
- fnschool/canteen/spreadsheet/workbook.py +0 -17
- fnschool/canteen/test.py +0 -97
- fnschool/config.py +0 -48
- fnschool/entry.py +0 -67
- fnschool/exam/__init__.py +0 -8
- fnschool/exam/data/parental_emails.xlsx +0 -0
- fnschool/exam/data/score.xlsx +0 -0
- fnschool/exam/email.py +0 -349
- fnschool/exam/entry.py +0 -36
- fnschool/exam/language.py +0 -19
- fnschool/exam/path.py +0 -24
- fnschool/exam/score.py +0 -1191
- fnschool/exam/subject.py +0 -20
- fnschool/exam/teacher.py +0 -54
- fnschool/external.py +0 -89
- fnschool/games/__init__.py +0 -1
- fnschool/games/__main__.py +0 -1
- fnschool/games/games.py +0 -1
- fnschool/inoutput.py +0 -97
- fnschool/language.py +0 -40
- fnschool/locales/en_US/LC_MESSAGES/fnschool.mo +0 -0
- fnschool/locales/zh_CN/LC_MESSAGES/fnschool.mo +0 -0
- fnschool/locales/zh_HK/LC_MESSAGES/fnschool.mo +0 -0
- fnschool/locales/zh_SG/LC_MESSAGES/fnschool.mo +0 -0
- fnschool/locales/zh_TW/LC_MESSAGES/fnschool.mo +0 -0
- fnschool/path.py +0 -45
- fnschool/test.py +0 -24
- fnschool/user.py +0 -262
- fnschool-20250109.80500.803.dist-info/METADATA +0 -342
- fnschool-20250109.80500.803.dist-info/RECORD +0 -78
- fnschool-20250109.80500.803.dist-info/entry_points.txt +0 -5
- fnschool-20250109.80500.803.dist-info/top_level.txt +0 -1
- /fnschool/canteen/consume.py → /fnschoo1/canteen/__init__.py +0 -0
- /fnschool/canteen/food_recount.toml → /fnschoo1/canteen/migrations/__init__.py +0 -0
- {fnschool/canteen/spreadsheet → fnschoo1/canteen/workbook}/__init__.py +0 -0
- /fnschool/exam/__main__.py → /fnschoo1/fnschool/templatetags/__init__.py +0 -0
- /fnschool/canteen/food_recounts.toml → /fnschoo1/profiles/__init__.py +0 -0
- /fnschool/canteen/warehouse.py → /fnschoo1/profiles/migrations/__init__.py +0 -0
- /fnschool/canteen/workbook.toml → /fnschoo1/templates/base/_content.html +0 -0
- {fnschool-20250109.80500.803.dist-info → fnschool-20251011.80531.840.dist-info/licenses}/LICENSE +0 -0
fnschoo1/db.sqlite3
ADDED
|
Binary file
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import re
|
|
2
|
+
|
|
3
|
+
from django.utils.translation import gettext # as _
|
|
4
|
+
from django.utils.translation import gettext_lazy as _
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def count_chinese_characters(text):
|
|
8
|
+
pattern = re.compile(r"[\u4e00-\u9fa5]")
|
|
9
|
+
chinese_chars = pattern.findall(text)
|
|
10
|
+
return len(chinese_chars)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
# The end.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"""
|
|
2
|
+
ASGI config for fnschool project.
|
|
3
|
+
|
|
4
|
+
It exposes the ASGI callable as a module-level variable named ``application``.
|
|
5
|
+
|
|
6
|
+
For more information on this file, see
|
|
7
|
+
https://docs.djangoproject.com/en/4.2/howto/deployment/asgi/
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import os
|
|
11
|
+
|
|
12
|
+
from django.core.asgi import get_asgi_application
|
|
13
|
+
|
|
14
|
+
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "fnschool.settings")
|
|
15
|
+
|
|
16
|
+
application = get_asgi_application()
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Django settings for fnschool project.
|
|
3
|
+
|
|
4
|
+
Generated by 'django-admin startproject' using Django 4.2.24.
|
|
5
|
+
|
|
6
|
+
For more information on this file, see
|
|
7
|
+
https://docs.djangoproject.com/en/4.2/topics/settings/
|
|
8
|
+
|
|
9
|
+
For the full list of settings and their values, see
|
|
10
|
+
https://docs.djangoproject.com/en/4.2/ref/settings/
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
import os
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
|
|
16
|
+
from django.urls import reverse_lazy
|
|
17
|
+
from django.utils.translation import gettext_lazy as _
|
|
18
|
+
|
|
19
|
+
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
|
20
|
+
BASE_DIR = Path(__file__).resolve().parent.parent
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
# Quick-start development settings - unsuitable for production
|
|
24
|
+
# See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/
|
|
25
|
+
|
|
26
|
+
# SECURITY WARNING: keep the secret key used in production secret!
|
|
27
|
+
SECRET_KEY = (
|
|
28
|
+
"django-insecure-vt(#owf#cbx)yo$9m^=%&-heu&txuc23&a5b=a=u@=274)2!9w"
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
# SECURITY WARNING: don't run with debug turned on in production!
|
|
32
|
+
DEBUG = True
|
|
33
|
+
|
|
34
|
+
ALLOWED_HOSTS = []
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
# Application definition
|
|
38
|
+
|
|
39
|
+
INSTALLED_APPS = [
|
|
40
|
+
"django.contrib.admin",
|
|
41
|
+
"django.contrib.auth",
|
|
42
|
+
"django.contrib.contenttypes",
|
|
43
|
+
"django.contrib.sessions",
|
|
44
|
+
"django.contrib.messages",
|
|
45
|
+
"django.contrib.staticfiles",
|
|
46
|
+
# site apps.
|
|
47
|
+
"crispy_forms",
|
|
48
|
+
"crispy_bootstrap5", # For Bootstrap 5
|
|
49
|
+
# fnschool apps.
|
|
50
|
+
"fnschool",
|
|
51
|
+
"profiles",
|
|
52
|
+
"canteen",
|
|
53
|
+
]
|
|
54
|
+
|
|
55
|
+
CRISPY_ALLOWED_TEMPLATE_PACKS = "bootstrap5"
|
|
56
|
+
CRISPY_TEMPLATE_PACK = "bootstrap5"
|
|
57
|
+
|
|
58
|
+
MIDDLEWARE = [
|
|
59
|
+
"django.middleware.security.SecurityMiddleware",
|
|
60
|
+
"django.contrib.sessions.middleware.SessionMiddleware",
|
|
61
|
+
"django.middleware.locale.LocaleMiddleware",
|
|
62
|
+
"django.middleware.common.CommonMiddleware",
|
|
63
|
+
"django.middleware.csrf.CsrfViewMiddleware",
|
|
64
|
+
"django.contrib.auth.middleware.AuthenticationMiddleware",
|
|
65
|
+
"django.contrib.messages.middleware.MessageMiddleware",
|
|
66
|
+
"django.middleware.clickjacking.XFrameOptionsMiddleware",
|
|
67
|
+
]
|
|
68
|
+
|
|
69
|
+
ROOT_URLCONF = "fnschool.urls"
|
|
70
|
+
|
|
71
|
+
TEMPLATES = [
|
|
72
|
+
{
|
|
73
|
+
"BACKEND": "django.template.backends.django.DjangoTemplates",
|
|
74
|
+
"DIRS": [
|
|
75
|
+
os.path.join(BASE_DIR, "templates"),
|
|
76
|
+
],
|
|
77
|
+
"APP_DIRS": True,
|
|
78
|
+
"OPTIONS": {
|
|
79
|
+
"context_processors": [
|
|
80
|
+
"django.template.context_processors.debug",
|
|
81
|
+
"django.template.context_processors.request",
|
|
82
|
+
"django.contrib.auth.context_processors.auth",
|
|
83
|
+
"django.contrib.messages.context_processors.messages",
|
|
84
|
+
"django.template.context_processors.i18n",
|
|
85
|
+
],
|
|
86
|
+
"builtins": [
|
|
87
|
+
"django.templatetags.i18n",
|
|
88
|
+
],
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
]
|
|
92
|
+
|
|
93
|
+
WSGI_APPLICATION = "fnschool.wsgi.application"
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
# Database
|
|
97
|
+
# https://docs.djangoproject.com/en/4.2/ref/settings/#databases
|
|
98
|
+
|
|
99
|
+
DATABASES = {
|
|
100
|
+
"default": {
|
|
101
|
+
"ENGINE": "django.db.backends.sqlite3",
|
|
102
|
+
"NAME": BASE_DIR / "db.sqlite3",
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
# Password validation
|
|
108
|
+
# https://docs.djangoproject.com/en/4.2/ref/settings/#auth-password-validators
|
|
109
|
+
AUTH_USER_MODEL = "profiles.Profile"
|
|
110
|
+
AUTH_PASSWORD_VALIDATORS = [
|
|
111
|
+
{
|
|
112
|
+
"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",
|
|
122
|
+
},
|
|
123
|
+
]
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
# Internationalization
|
|
127
|
+
# https://docs.djangoproject.com/en/4.2/topics/i18n/
|
|
128
|
+
|
|
129
|
+
TIME_ZONE = "UTC"
|
|
130
|
+
|
|
131
|
+
USE_I18N = True
|
|
132
|
+
USE_L10N = True
|
|
133
|
+
|
|
134
|
+
LANGUAGE_CODE = "zh-hans"
|
|
135
|
+
|
|
136
|
+
LANGUAGES = [
|
|
137
|
+
("en", _("English")),
|
|
138
|
+
("es", _("Spanish")),
|
|
139
|
+
("fr", _("French")),
|
|
140
|
+
("zh-hans", _("Simplified Chinese")),
|
|
141
|
+
]
|
|
142
|
+
LOCALE_PATHS = [
|
|
143
|
+
os.path.join(BASE_DIR, "locale"),
|
|
144
|
+
]
|
|
145
|
+
|
|
146
|
+
USE_TZ = True
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
# Static files (CSS, JavaScript, Images)
|
|
150
|
+
# https://docs.djangoproject.com/en/4.2/howto/static-files/
|
|
151
|
+
|
|
152
|
+
STATIC_URL = "/static/"
|
|
153
|
+
STATICFILES_DIRS = [
|
|
154
|
+
os.path.join(BASE_DIR, "static")
|
|
155
|
+
] # Optional: for additional static directories
|
|
156
|
+
STATIC_ROOT = os.path.join(BASE_DIR, "static_collected")
|
|
157
|
+
|
|
158
|
+
# Default primary key field type
|
|
159
|
+
# https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field
|
|
160
|
+
|
|
161
|
+
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
|
|
162
|
+
|
|
163
|
+
MEDIA_URL = "/media/"
|
|
164
|
+
MEDIA_ROOT = os.path.join(BASE_DIR, "media")
|
|
165
|
+
|
|
166
|
+
LOGIN_URL = reverse_lazy("profiles:log_in")
|
|
167
|
+
# The end.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
from urllib.parse import urlencode
|
|
2
|
+
|
|
3
|
+
from django import template
|
|
4
|
+
|
|
5
|
+
register = template.Library()
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@register.simple_tag(takes_context=True)
|
|
9
|
+
def param_replace(context, **kwargs):
|
|
10
|
+
query = context["request"].GET.copy()
|
|
11
|
+
|
|
12
|
+
for key, value in kwargs.items():
|
|
13
|
+
if value is None:
|
|
14
|
+
if key in query:
|
|
15
|
+
del query[key]
|
|
16
|
+
else:
|
|
17
|
+
query[key] = value
|
|
18
|
+
|
|
19
|
+
return urlencode(query)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@register.simple_tag
|
|
23
|
+
def multiply(a, b, *args):
|
|
24
|
+
result = float(a) * float(b)
|
|
25
|
+
for arg in args:
|
|
26
|
+
result *= float(arg)
|
|
27
|
+
return result
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"""
|
|
2
|
+
URL configuration for fnschool project.
|
|
3
|
+
|
|
4
|
+
The `urlpatterns` list routes URLs to views. For more information please see:
|
|
5
|
+
https://docs.djangoproject.com/en/4.2/topics/http/urls/
|
|
6
|
+
Examples:
|
|
7
|
+
Function views
|
|
8
|
+
1. Add an import: from my_app import views
|
|
9
|
+
2. Add a URL to urlpatterns: path('', views.home, name='home')
|
|
10
|
+
Class-based views
|
|
11
|
+
1. Add an import: from other_app.views import Home
|
|
12
|
+
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
|
|
13
|
+
Including another URLconf
|
|
14
|
+
1. Import the include() function: from django.urls import include, path
|
|
15
|
+
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
from django.conf.urls.i18n import i18n_patterns
|
|
19
|
+
from django.contrib import admin
|
|
20
|
+
from django.urls import include, path
|
|
21
|
+
|
|
22
|
+
from . import views
|
|
23
|
+
|
|
24
|
+
urlpatterns = [
|
|
25
|
+
path("", views.home_view, name="home"),
|
|
26
|
+
path("admin/", admin.site.urls),
|
|
27
|
+
path("i18n/", include("django.conf.urls.i18n")),
|
|
28
|
+
path("profiles/", include("profiles.urls")),
|
|
29
|
+
path("canteen/", include("canteen.urls")),
|
|
30
|
+
]
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"""
|
|
2
|
+
WSGI config for fnschool project.
|
|
3
|
+
|
|
4
|
+
It exposes the WSGI callable as a module-level variable named ``application``.
|
|
5
|
+
|
|
6
|
+
For more information on this file, see
|
|
7
|
+
https://docs.djangoproject.com/en/4.2/howto/deployment/wsgi/
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import os
|
|
11
|
+
|
|
12
|
+
from django.core.wsgi import get_wsgi_application
|
|
13
|
+
|
|
14
|
+
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "fnschool.settings")
|
|
15
|
+
|
|
16
|
+
application = get_wsgi_application()
|
|
Binary file
|
|
Binary file
|
fnschoo1/manage.py
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Django's command-line utility for administrative tasks."""
|
|
3
|
+
import os
|
|
4
|
+
import platform
|
|
5
|
+
import random
|
|
6
|
+
import sys
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def main():
|
|
10
|
+
"""Run administrative tasks."""
|
|
11
|
+
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "fnschool.settings")
|
|
12
|
+
try:
|
|
13
|
+
from django.core.management import execute_from_command_line
|
|
14
|
+
except ImportError as exc:
|
|
15
|
+
raise ImportError(
|
|
16
|
+
"Couldn't import Django. Are you sure it's installed and "
|
|
17
|
+
"available on your PYTHONPATH environment variable? Did you "
|
|
18
|
+
"forget to activate a virtual environment?"
|
|
19
|
+
) from exc
|
|
20
|
+
|
|
21
|
+
execute_from_command_line(sys.argv)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
if __name__ == "__main__":
|
|
25
|
+
main()
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
from django.contrib import admin
|
|
2
|
+
|
|
3
|
+
from .models import Profile
|
|
4
|
+
|
|
5
|
+
# Register your models here.
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@admin.register(Profile)
|
|
9
|
+
class ProfileAdmin(admin.ModelAdmin):
|
|
10
|
+
list_display = [
|
|
11
|
+
"user",
|
|
12
|
+
"phone",
|
|
13
|
+
"affiliation",
|
|
14
|
+
"superior_department",
|
|
15
|
+
"date_of_birth",
|
|
16
|
+
"address",
|
|
17
|
+
]
|
|
18
|
+
search_fields = ["user__username", "phone", "address"]
|
|
19
|
+
list_filter = ["date_of_birth"]
|
|
20
|
+
|
|
21
|
+
def user(self, obj):
|
|
22
|
+
if obj:
|
|
23
|
+
return obj.username
|
|
24
|
+
return "No User"
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
# The end.
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
from datetime import date
|
|
2
|
+
|
|
3
|
+
from django import forms
|
|
4
|
+
from django.contrib.auth.forms import AuthenticationForm
|
|
5
|
+
from django.forms import ModelForm
|
|
6
|
+
from fnschool import _
|
|
7
|
+
|
|
8
|
+
from .models import Profile
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class ProfileLoginForm(AuthenticationForm):
|
|
12
|
+
username = forms.CharField(
|
|
13
|
+
label=_("User Name"),
|
|
14
|
+
widget=forms.TextInput(attrs={"placeholder": _("User Name")}),
|
|
15
|
+
)
|
|
16
|
+
password = forms.CharField(
|
|
17
|
+
label=_("Password"),
|
|
18
|
+
widget=forms.PasswordInput(attrs={"placeholder": _("Password")}),
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class ProfileForm(ModelForm):
|
|
23
|
+
username = forms.CharField(
|
|
24
|
+
max_length=128,
|
|
25
|
+
label=_("User Name"),
|
|
26
|
+
widget=forms.TextInput(attrs={"placeholder": _("User Name")}),
|
|
27
|
+
)
|
|
28
|
+
password = forms.CharField(
|
|
29
|
+
label=_("Password"),
|
|
30
|
+
widget=forms.PasswordInput(attrs={"placeholder": _("Password")}),
|
|
31
|
+
)
|
|
32
|
+
password_confirm = forms.CharField(
|
|
33
|
+
label=_("Confirm Password"),
|
|
34
|
+
widget=forms.PasswordInput(
|
|
35
|
+
attrs={"placeholder": _("Confirm Password")}
|
|
36
|
+
),
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
class Meta:
|
|
40
|
+
current_year = date.today().year
|
|
41
|
+
year_range = list(range(current_year - 100, current_year + 1))
|
|
42
|
+
model = Profile
|
|
43
|
+
fields = [
|
|
44
|
+
"username",
|
|
45
|
+
"phone",
|
|
46
|
+
"affiliation",
|
|
47
|
+
"superior_department",
|
|
48
|
+
"date_of_birth",
|
|
49
|
+
"gender",
|
|
50
|
+
"address",
|
|
51
|
+
"avatar",
|
|
52
|
+
"bio",
|
|
53
|
+
]
|
|
54
|
+
widgets = {
|
|
55
|
+
"date_of_birth": forms.SelectDateWidget(
|
|
56
|
+
years=year_range,
|
|
57
|
+
attrs={"style": "width: 33.33%; display: inline-block;"},
|
|
58
|
+
)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
def clean(self):
|
|
62
|
+
cleaned_data = super().clean()
|
|
63
|
+
if cleaned_data.get("password") != cleaned_data.get("password_confirm"):
|
|
64
|
+
raise forms.ValidationError("Passwords do not match")
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
# The end.
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
# Generated by Django 4.2.24 on 2025-09-24 19:48
|
|
2
|
+
|
|
3
|
+
import django.contrib.auth.models
|
|
4
|
+
import django.contrib.auth.validators
|
|
5
|
+
import django.utils.timezone
|
|
6
|
+
from django.db import migrations, models
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class Migration(migrations.Migration):
|
|
10
|
+
|
|
11
|
+
initial = True
|
|
12
|
+
|
|
13
|
+
dependencies = [
|
|
14
|
+
("auth", "0012_alter_user_first_name_max_length"),
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
operations = [
|
|
18
|
+
migrations.CreateModel(
|
|
19
|
+
name="Profile",
|
|
20
|
+
fields=[
|
|
21
|
+
(
|
|
22
|
+
"id",
|
|
23
|
+
models.BigAutoField(
|
|
24
|
+
auto_created=True,
|
|
25
|
+
primary_key=True,
|
|
26
|
+
serialize=False,
|
|
27
|
+
verbose_name="ID",
|
|
28
|
+
),
|
|
29
|
+
),
|
|
30
|
+
(
|
|
31
|
+
"password",
|
|
32
|
+
models.CharField(max_length=128, verbose_name="password"),
|
|
33
|
+
),
|
|
34
|
+
(
|
|
35
|
+
"last_login",
|
|
36
|
+
models.DateTimeField(
|
|
37
|
+
blank=True, null=True, verbose_name="last login"
|
|
38
|
+
),
|
|
39
|
+
),
|
|
40
|
+
(
|
|
41
|
+
"is_superuser",
|
|
42
|
+
models.BooleanField(
|
|
43
|
+
default=False,
|
|
44
|
+
help_text="Designates that this user has all permissions without explicitly assigning them.",
|
|
45
|
+
verbose_name="superuser status",
|
|
46
|
+
),
|
|
47
|
+
),
|
|
48
|
+
(
|
|
49
|
+
"username",
|
|
50
|
+
models.CharField(
|
|
51
|
+
error_messages={
|
|
52
|
+
"unique": "A user with that username already exists."
|
|
53
|
+
},
|
|
54
|
+
help_text="Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.",
|
|
55
|
+
max_length=150,
|
|
56
|
+
unique=True,
|
|
57
|
+
validators=[
|
|
58
|
+
django.contrib.auth.validators.UnicodeUsernameValidator()
|
|
59
|
+
],
|
|
60
|
+
verbose_name="username",
|
|
61
|
+
),
|
|
62
|
+
),
|
|
63
|
+
(
|
|
64
|
+
"first_name",
|
|
65
|
+
models.CharField(
|
|
66
|
+
blank=True, max_length=150, verbose_name="first name"
|
|
67
|
+
),
|
|
68
|
+
),
|
|
69
|
+
(
|
|
70
|
+
"last_name",
|
|
71
|
+
models.CharField(
|
|
72
|
+
blank=True, max_length=150, verbose_name="last name"
|
|
73
|
+
),
|
|
74
|
+
),
|
|
75
|
+
(
|
|
76
|
+
"email",
|
|
77
|
+
models.EmailField(
|
|
78
|
+
blank=True, max_length=254, verbose_name="email address"
|
|
79
|
+
),
|
|
80
|
+
),
|
|
81
|
+
(
|
|
82
|
+
"is_staff",
|
|
83
|
+
models.BooleanField(
|
|
84
|
+
default=False,
|
|
85
|
+
help_text="Designates whether the user can log into this admin site.",
|
|
86
|
+
verbose_name="staff status",
|
|
87
|
+
),
|
|
88
|
+
),
|
|
89
|
+
(
|
|
90
|
+
"is_active",
|
|
91
|
+
models.BooleanField(
|
|
92
|
+
default=True,
|
|
93
|
+
help_text="Designates whether this user should be treated as active. Unselect this instead of deleting accounts.",
|
|
94
|
+
verbose_name="active",
|
|
95
|
+
),
|
|
96
|
+
),
|
|
97
|
+
(
|
|
98
|
+
"date_joined",
|
|
99
|
+
models.DateTimeField(
|
|
100
|
+
default=django.utils.timezone.now,
|
|
101
|
+
verbose_name="date joined",
|
|
102
|
+
),
|
|
103
|
+
),
|
|
104
|
+
(
|
|
105
|
+
"phone",
|
|
106
|
+
models.CharField(
|
|
107
|
+
blank=True,
|
|
108
|
+
max_length=15,
|
|
109
|
+
null=True,
|
|
110
|
+
verbose_name="Phone Number",
|
|
111
|
+
),
|
|
112
|
+
),
|
|
113
|
+
(
|
|
114
|
+
"affiliation",
|
|
115
|
+
models.CharField(
|
|
116
|
+
blank=True,
|
|
117
|
+
max_length=255,
|
|
118
|
+
null=True,
|
|
119
|
+
verbose_name="Affiliation",
|
|
120
|
+
),
|
|
121
|
+
),
|
|
122
|
+
(
|
|
123
|
+
"superior_department",
|
|
124
|
+
models.CharField(
|
|
125
|
+
blank=True,
|
|
126
|
+
max_length=255,
|
|
127
|
+
null=True,
|
|
128
|
+
verbose_name="Superior department",
|
|
129
|
+
),
|
|
130
|
+
),
|
|
131
|
+
(
|
|
132
|
+
"date_of_birth",
|
|
133
|
+
models.DateField(
|
|
134
|
+
blank=True, null=True, verbose_name="Date of Birth"
|
|
135
|
+
),
|
|
136
|
+
),
|
|
137
|
+
(
|
|
138
|
+
"address",
|
|
139
|
+
models.CharField(
|
|
140
|
+
blank=True,
|
|
141
|
+
max_length=255,
|
|
142
|
+
null=True,
|
|
143
|
+
verbose_name="Address",
|
|
144
|
+
),
|
|
145
|
+
),
|
|
146
|
+
(
|
|
147
|
+
"avatar",
|
|
148
|
+
models.ImageField(
|
|
149
|
+
blank=True,
|
|
150
|
+
null=True,
|
|
151
|
+
upload_to="avatars/",
|
|
152
|
+
verbose_name="Avatar",
|
|
153
|
+
),
|
|
154
|
+
),
|
|
155
|
+
(
|
|
156
|
+
"bio",
|
|
157
|
+
models.TextField(
|
|
158
|
+
blank=True, max_length=512, verbose_name=""
|
|
159
|
+
),
|
|
160
|
+
),
|
|
161
|
+
(
|
|
162
|
+
"groups",
|
|
163
|
+
models.ManyToManyField(
|
|
164
|
+
blank=True,
|
|
165
|
+
help_text="The groups this user belongs to. A user will get all permissions granted to each of their groups.",
|
|
166
|
+
related_name="user_set",
|
|
167
|
+
related_query_name="user",
|
|
168
|
+
to="auth.group",
|
|
169
|
+
verbose_name="groups",
|
|
170
|
+
),
|
|
171
|
+
),
|
|
172
|
+
(
|
|
173
|
+
"user_permissions",
|
|
174
|
+
models.ManyToManyField(
|
|
175
|
+
blank=True,
|
|
176
|
+
help_text="Specific permissions for this user.",
|
|
177
|
+
related_name="user_set",
|
|
178
|
+
related_query_name="user",
|
|
179
|
+
to="auth.permission",
|
|
180
|
+
verbose_name="user permissions",
|
|
181
|
+
),
|
|
182
|
+
),
|
|
183
|
+
],
|
|
184
|
+
options={
|
|
185
|
+
"verbose_name": "User Profile",
|
|
186
|
+
"verbose_name_plural": "User Profiles",
|
|
187
|
+
},
|
|
188
|
+
managers=[
|
|
189
|
+
("objects", django.contrib.auth.models.UserManager()),
|
|
190
|
+
],
|
|
191
|
+
),
|
|
192
|
+
]
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Generated by Django 4.2.24 on 2025-09-25 02:02
|
|
2
|
+
|
|
3
|
+
from django.db import migrations, models
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Migration(migrations.Migration):
|
|
7
|
+
|
|
8
|
+
dependencies = [
|
|
9
|
+
("profiles", "0001_initial"),
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
operations = [
|
|
13
|
+
migrations.AlterField(
|
|
14
|
+
model_name="profile",
|
|
15
|
+
name="bio",
|
|
16
|
+
field=models.TextField(
|
|
17
|
+
blank=True, max_length=512, verbose_name="Biography"
|
|
18
|
+
),
|
|
19
|
+
),
|
|
20
|
+
]
|