fnschool 20251021.80058.842__tar.gz → 20251027.82134.859__tar.gz

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.

Files changed (141) hide show
  1. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/PKG-INFO +1 -1
  2. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/__init__.py +1 -1
  3. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/canteen/forms.py +2 -2
  4. fnschool-20251027.82134.859/src/fnschoo1/canteen/migrations/0019_category_updated_at_ingredient_created_at_and_more.py +48 -0
  5. fnschool-20251027.82134.859/src/fnschoo1/canteen/migrations/0020_alter_ingredient_created_at.py +20 -0
  6. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/canteen/models.py +23 -3
  7. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/canteen/templates/canteen/category/list.html +1 -1
  8. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/canteen/templates/canteen/consumption/create.html +6 -1
  9. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/canteen/templates/canteen/ingredient/list.html +11 -2
  10. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/canteen/templates/canteen/meal_type/list.html +1 -1
  11. fnschool-20251027.82134.859/src/fnschoo1/fnprofile/admin.py +27 -0
  12. fnschool-20251027.82134.859/src/fnschoo1/fnprofile/apps.py +12 -0
  13. fnschool-20251027.82134.859/src/fnschoo1/fnprofile/forms.py +73 -0
  14. fnschool-20251027.82134.859/src/fnschoo1/fnprofile/migrations/0001_initial.py +213 -0
  15. fnschool-20251027.82134.859/src/fnschoo1/fnprofile/migrations/0002_auto_20251026_2235.py +42 -0
  16. fnschool-20251027.82134.859/src/fnschoo1/fnprofile/migrations/0003_alter_fnuser_options_alter_fnuser_groups_and_more.py +45 -0
  17. fnschool-20251027.82134.859/src/fnschoo1/fnprofile/models.py +90 -0
  18. fnschool-20251027.82134.859/src/fnschoo1/fnprofile/signals.py +20 -0
  19. fnschool-20251027.82134.859/src/fnschoo1/fnprofile/templates/fnprofile/create.html +18 -0
  20. fnschool-20251027.82134.859/src/fnschoo1/fnprofile/templates/fnprofile/detail.html +16 -0
  21. fnschool-20251027.82134.859/src/fnschoo1/fnprofile/templates/fnprofile/edit.html +16 -0
  22. fnschool-20251027.82134.859/src/fnschoo1/fnprofile/templates/fnprofile/log_in.html +22 -0
  23. fnschool-20251027.82134.859/src/fnschoo1/fnprofile/templates/fnprofile/log_out.html +12 -0
  24. fnschool-20251027.82134.859/src/fnschoo1/fnprofile/urls.py +15 -0
  25. fnschool-20251027.82134.859/src/fnschoo1/fnprofile/views.py +69 -0
  26. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/fnschool/settings.py +5 -3
  27. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/fnschool/urls.py +7 -2
  28. fnschool-20251027.82134.859/src/fnschoo1/locale/zh_Hans/LC_MESSAGES/django.mo +0 -0
  29. fnschool-20251027.82134.859/src/fnschoo1/profiles/__init__.py +7 -0
  30. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/profiles/forms.py +6 -0
  31. fnschool-20251027.82134.859/src/fnschoo1/profiles/migrations/0006_profile_created_at_profile_updated_at.py +27 -0
  32. fnschool-20251027.82134.859/src/fnschoo1/profiles/migrations/0007_alter_profile_created_at.py +20 -0
  33. fnschool-20251027.82134.859/src/fnschoo1/profiles/migrations/0008_alter_profile_groups_alter_profile_user_permissions.py +38 -0
  34. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/profiles/models.py +32 -2
  35. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/profiles/templates/profiles/create.html +1 -1
  36. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/profiles/templates/profiles/detail.html +1 -1
  37. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/profiles/templates/profiles/edit.html +4 -2
  38. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/profiles/templates/profiles/log_in.html +1 -1
  39. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/profiles/templates/profiles/log_out.html +1 -1
  40. fnschool-20251027.82134.859/src/fnschoo1/profiles/tests.py +3 -0
  41. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/profiles/views.py +7 -1
  42. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/static/css/fnschool.css +14 -0
  43. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/static/js/fnschool.js +20 -0
  44. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/templates/home.html +1 -1
  45. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/templates/includes/_header.html +30 -6
  46. fnschool-20251027.82134.859/src/fnschoo1/templates/registration/login.html +0 -0
  47. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschool.egg-info/PKG-INFO +1 -1
  48. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschool.egg-info/SOURCES.txt +24 -1
  49. fnschool-20251021.80058.842/src/fnschoo1/locale/zh_Hans/LC_MESSAGES/django.mo +0 -0
  50. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/LICENSE +0 -0
  51. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/README.md +0 -0
  52. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/pyproject.toml +0 -0
  53. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/setup.cfg +0 -0
  54. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/canteen/__init__.py +0 -0
  55. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/canteen/admin.py +0 -0
  56. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/canteen/apps.py +0 -0
  57. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/canteen/migrations/0001_initial.py +0 -0
  58. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/canteen/migrations/0002_ingredient_is_disabled.py +0 -0
  59. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/canteen/migrations/0003_consumption_is_disabled_alter_ingredient_is_disabled.py +0 -0
  60. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/canteen/migrations/0004_alter_ingredient_name_category_and_more.py +0 -0
  61. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/canteen/migrations/0005_alter_category_created_at_alter_category_name_and_more.py +0 -0
  62. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/canteen/migrations/0006_category_is_disabled_alter_category_user_and_more.py +0 -0
  63. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/canteen/migrations/0007_alter_consumption_amount_used_and_more.py +0 -0
  64. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/canteen/migrations/0008_category_abbreviation_mealtype.py +0 -0
  65. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/canteen/migrations/0009_alter_category_abbreviation_and_more.py +0 -0
  66. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/canteen/migrations/0010_alter_consumption_options_alter_ingredient_options_and_more.py +0 -0
  67. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/canteen/migrations/0011_category_pin_to_consumptions_top.py +0 -0
  68. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/canteen/migrations/0012_alter_ingredient_storage_date.py +0 -0
  69. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/canteen/migrations/0013_alter_consumption_options_alter_ingredient_options_and_more.py +0 -0
  70. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/canteen/migrations/0014_category_priority.py +0 -0
  71. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/canteen/migrations/0015_alter_category_options_alter_category_priority.py +0 -0
  72. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/canteen/migrations/0016_consumption_unique_ingredient_date_of_using.py +0 -0
  73. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/canteen/migrations/0017_ingredient_updated_at_alter_category_created_at_and_more.py +0 -0
  74. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/canteen/migrations/0018_alter_ingredient_updated_at.py +0 -0
  75. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/canteen/migrations/__init__.py +0 -0
  76. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/canteen/templates/canteen/category/create.html +0 -0
  77. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/canteen/templates/canteen/category/delete.html +0 -0
  78. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/canteen/templates/canteen/category/update.html +0 -0
  79. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/canteen/templates/canteen/close.html +0 -0
  80. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/canteen/templates/canteen/consumption/_create.html +0 -0
  81. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/canteen/templates/canteen/ingredient/close.html +0 -0
  82. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/canteen/templates/canteen/ingredient/create.html +0 -0
  83. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/canteen/templates/canteen/ingredient/create_one.html +0 -0
  84. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/canteen/templates/canteen/ingredient/delete.html +0 -0
  85. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/canteen/templates/canteen/ingredient/update.html +0 -0
  86. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/canteen/templates/canteen/meal_type/create.html +0 -0
  87. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/canteen/templates/canteen/meal_type/delete.html +0 -0
  88. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/canteen/templates/canteen/meal_type/update.html +0 -0
  89. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/canteen/tests.py +0 -0
  90. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/canteen/urls.py +0 -0
  91. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/canteen/views.py +0 -0
  92. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/canteen/workbook/__init__.py +0 -0
  93. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/canteen/workbook/generate.py +0 -0
  94. {fnschool-20251021.80058.842/src/fnschoo1/profiles → fnschool-20251027.82134.859/src/fnschoo1/fnprofile}/__init__.py +0 -0
  95. {fnschool-20251021.80058.842/src/fnschoo1/profiles → fnschool-20251027.82134.859/src/fnschoo1/fnprofile}/migrations/__init__.py +0 -0
  96. {fnschool-20251021.80058.842/src/fnschoo1/profiles → fnschool-20251027.82134.859/src/fnschoo1/fnprofile}/tests.py +0 -0
  97. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/fnschool/__init__.py +0 -0
  98. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/fnschool/_settings.py +0 -0
  99. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/fnschool/asgi.py +0 -0
  100. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/fnschool/templatetags/__init__.py +0 -0
  101. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/fnschool/templatetags/fnschool_tags.py +0 -0
  102. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/fnschool/views.py +0 -0
  103. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/fnschool/wsgi.py +0 -0
  104. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/locale/en/LC_MESSAGES/django.mo +0 -0
  105. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/manage.py +0 -0
  106. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/profiles/admin.py +0 -0
  107. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/profiles/apps.py +0 -0
  108. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/profiles/migrations/0001_initial.py +0 -0
  109. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/profiles/migrations/0002_alter_profile_bio.py +0 -0
  110. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/profiles/migrations/0003_alter_profile_options_alter_profile_address_and_more.py +0 -0
  111. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/profiles/migrations/0004_profile_gender.py +0 -0
  112. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/profiles/migrations/0005_alter_profile_gender.py +0 -0
  113. /fnschool-20251021.80058.842/src/fnschoo1/templates/base/_content.html → /fnschool-20251027.82134.859/src/fnschoo1/profiles/migrations/__init__.py +0 -0
  114. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/profiles/signals.py +0 -0
  115. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/profiles/urls.py +0 -0
  116. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/static/css/bootstrap.min.css +0 -0
  117. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/static/images/favicon.ico +0 -0
  118. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/static/js/bootstrap.bundle.min.js +0 -0
  119. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/static/js/bootstrap.min.js +0 -0
  120. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/static/js/jquery.min.js +0 -0
  121. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/static/js/jquery.slim.min.js +0 -0
  122. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/static/js/popper.min.js +0 -0
  123. /fnschool-20251021.80058.842/src/fnschoo1/templates/includes/_navigation.html → /fnschool-20251027.82134.859/src/fnschoo1/templates/base/_content.html +0 -0
  124. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/templates/base/_css.html +0 -0
  125. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/templates/base/_js.html +0 -0
  126. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/templates/base/content.html +0 -0
  127. /fnschool-20251021.80058.842/src/fnschoo1/templates/base/header_content_footer.html → /fnschool-20251027.82134.859/src/fnschoo1/templates/base/document.html +0 -0
  128. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/templates/close.html +0 -0
  129. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/templates/includes/_footer.html +0 -0
  130. /fnschool-20251021.80058.842/src/fnschoo1/templates/registration/logged_out.html → /fnschool-20251027.82134.859/src/fnschoo1/templates/includes/_navigation.html +0 -0
  131. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschoo1/templates/includes/_paginator.html +0 -0
  132. /fnschool-20251021.80058.842/src/fnschoo1/templates/registration/login.html → /fnschool-20251027.82134.859/src/fnschoo1/templates/registration/logged_out.html +0 -0
  133. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschool.egg-info/SOURCES.txt.py +0 -0
  134. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschool.egg-info/dependency_links.txt +0 -0
  135. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschool.egg-info/dependency_links.txt.py +0 -0
  136. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschool.egg-info/entry_points.txt +0 -0
  137. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschool.egg-info/entry_points.txt.py +0 -0
  138. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschool.egg-info/requires.txt +0 -0
  139. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschool.egg-info/requires.txt.py +0 -0
  140. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschool.egg-info/top_level.txt +0 -0
  141. {fnschool-20251021.80058.842 → fnschool-20251027.82134.859}/src/fnschool.egg-info/top_level.txt.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fnschool
3
- Version: 20251021.80058.842
3
+ Version: 20251027.82134.859
4
4
  Summary: Just some school related scripts, without any ambition.
5
5
  Author-email: larryw3i <larryw3i@163.com>, Larry Wei <larryw3i@126.com>, Larry W3i <larryw3i@yeah.net>
6
6
  Maintainer-email: larryw3i <larryw3i@163.com>, Larry Wei <larryw3i@126.com>
@@ -6,4 +6,4 @@ import random
6
6
  import sys
7
7
  from pathlib import Path
8
8
 
9
- __version__ = "20251021.80058.842"
9
+ __version__ = "20251027.82134.859"
@@ -20,7 +20,7 @@ class IngredientForm(forms.ModelForm):
20
20
  fields = [
21
21
  f.name
22
22
  for f in Ingredient._meta.fields
23
- if f.name not in ["id", "user", "updated_at"]
23
+ if f.name not in ["id", "user", "updated_at", "created_at"]
24
24
  ]
25
25
 
26
26
  current_year = date.today().year
@@ -55,7 +55,7 @@ class ConsumptionForm(forms.ModelForm):
55
55
  widgets = {
56
56
  "amount_used": forms.NumberInput(
57
57
  attrs={
58
- "style": "width: 109px; text-align: center; font-family: Mono;"
58
+ "style": "width: 95px; text-align: center; font-family: Mono;"
59
59
  }
60
60
  ),
61
61
  "date_of_using": forms.HiddenInput(),
@@ -0,0 +1,48 @@
1
+ # Generated by Django 4.2.25 on 2025-10-24 01:44
2
+
3
+ from django.db import migrations, models
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+
8
+ dependencies = [
9
+ ("canteen", "0018_alter_ingredient_updated_at"),
10
+ ]
11
+
12
+ operations = [
13
+ migrations.AddField(
14
+ model_name="category",
15
+ name="updated_at",
16
+ field=models.DateTimeField(
17
+ auto_now=True, null=True, verbose_name="更新时间"
18
+ ),
19
+ ),
20
+ migrations.AddField(
21
+ model_name="ingredient",
22
+ name="created_at",
23
+ field=models.DateTimeField(
24
+ auto_now_add=True, null=True, verbose_name="Time of creating"
25
+ ),
26
+ ),
27
+ migrations.AddField(
28
+ model_name="mealtype",
29
+ name="updated_at",
30
+ field=models.DateTimeField(
31
+ auto_now=True, null=True, verbose_name="更新时间"
32
+ ),
33
+ ),
34
+ migrations.AlterField(
35
+ model_name="category",
36
+ name="created_at",
37
+ field=models.DateTimeField(
38
+ auto_now_add=True, null=True, verbose_name="创建日期"
39
+ ),
40
+ ),
41
+ migrations.AlterField(
42
+ model_name="mealtype",
43
+ name="created_at",
44
+ field=models.DateTimeField(
45
+ auto_now_add=True, null=True, verbose_name="创建日期"
46
+ ),
47
+ ),
48
+ ]
@@ -0,0 +1,20 @@
1
+ # Generated by Django 4.2.25 on 2025-10-24 15:20
2
+
3
+ from django.db import migrations, models
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+
8
+ dependencies = [
9
+ ("canteen", "0019_category_updated_at_ingredient_created_at_and_more"),
10
+ ]
11
+
12
+ operations = [
13
+ migrations.AlterField(
14
+ model_name="ingredient",
15
+ name="created_at",
16
+ field=models.DateTimeField(
17
+ auto_now_add=True, null=True, verbose_name="创建时间"
18
+ ),
19
+ ),
20
+ ]
@@ -22,8 +22,15 @@ class MealType(models.Model):
22
22
  null=True, blank=True, max_length=100, verbose_name=_("Abbreviation")
23
23
  )
24
24
  created_at = models.DateTimeField(
25
- null=True, verbose_name=_("Creating Date")
25
+ null=True,
26
+ blank=True,
27
+ auto_now_add=True,
28
+ verbose_name=_("Creating Date"),
29
+ )
30
+ updated_at = models.DateTimeField(
31
+ null=True, blank=True, auto_now=True, verbose_name=_("Time of updating")
26
32
  )
33
+
27
34
  is_disabled = models.BooleanField(
28
35
  default=False, verbose_name=_("Is Disabled")
29
36
  )
@@ -44,8 +51,12 @@ class Category(models.Model):
44
51
  null=True, blank=True, max_length=100, verbose_name=_("abbreviation")
45
52
  )
46
53
  created_at = models.DateTimeField(
47
- null=True, verbose_name=_("Creating Date")
54
+ null=True, auto_now_add=True, verbose_name=_("Creating Date")
55
+ )
56
+ updated_at = models.DateTimeField(
57
+ null=True, blank=True, auto_now=True, verbose_name=_("Time of updating")
48
58
  )
59
+
49
60
  is_disabled = models.BooleanField(
50
61
  default=False, verbose_name=_("Is Disabled")
51
62
  )
@@ -78,9 +89,18 @@ class Ingredient(models.Model):
78
89
  verbose_name=_("User"),
79
90
  )
80
91
  storage_date = models.DateField(verbose_name=_("Storage Date"))
92
+
93
+ created_at = models.DateTimeField(
94
+ null=True,
95
+ blank=True,
96
+ auto_now_add=True,
97
+ verbose_name=_("Time of creating"),
98
+ )
99
+
81
100
  updated_at = models.DateTimeField(
82
- null=True, auto_now=True, verbose_name=_("Time of updating")
101
+ null=True, blank=True, auto_now=True, verbose_name=_("Time of updating")
83
102
  )
103
+
84
104
  name = models.CharField(max_length=100, verbose_name=_("Ingredient Name"))
85
105
  meal_type = models.ForeignKey(
86
106
  MealType,
@@ -1,4 +1,4 @@
1
- {% extends "base/header_content_footer.html" %}
1
+ {% extends "base/document.html" %}
2
2
  {% load crispy_forms_tags %}
3
3
  {% block title %}
4
4
  {% trans "Category list" %}
@@ -1,4 +1,4 @@
1
- {% extends "base/header_content_footer.html" %}
1
+ {% extends "base/document.html" %}
2
2
  {% load crispy_forms_tags %}
3
3
  {% block title %}
4
4
  {% trans "Consume Ingredients" %}
@@ -22,6 +22,11 @@
22
22
  target="canteen_list_categories"
23
23
  href="{% url "canteen:list_categories" %}">{% trans "Ingredient Categories" %}</a>
24
24
 
25
+ <a class="btn btn-primary col-md-1 col-lg-1 col-2 "
26
+ target="canteen_list_meal_types"
27
+ href="{% url "canteen:list_meal_types" %}">{% trans "Ingredient Meal Types" %}</a>
28
+
29
+
25
30
  <div class="col col-3 col-md-2 col-lg-2">
26
31
  <input class=" form-control"
27
32
  onkeydown="if(event.keyCode==13){list_consumptions();}"
@@ -1,4 +1,4 @@
1
- {% extends "base/header_content_footer.html" %}
1
+ {% extends "base/document.html" %}
2
2
  {% load tz %}
3
3
  {% load crispy_forms_tags %}
4
4
  {% block title %}
@@ -112,7 +112,7 @@
112
112
  </div>
113
113
  {% include 'includes/_paginator.html' %}
114
114
  <script>
115
- $(document).ready(function() {
115
+ function set_ingredient_table_height() {
116
116
  var ingredient_table = $('.table-ingredient')
117
117
  var pagination = $('.pagination')
118
118
  var footer = $("footer")
@@ -120,7 +120,16 @@
120
120
  ingredient_table.parent().height(
121
121
  height
122
122
  );
123
+ }
124
+
125
+ $(document).ready(function() {
126
+ set_ingredient_table_height();
123
127
  });
128
+
129
+ $(window).resize(function() {
130
+ set_ingredient_table_height();
131
+ });
132
+
124
133
  $(document).ready(
125
134
  function() {
126
135
  make_highlight(".tr-ingredient", "ingredient_updated_at")
@@ -1,4 +1,4 @@
1
- {% extends "base/header_content_footer.html" %}
1
+ {% extends "base/document.html" %}
2
2
  {% load crispy_forms_tags %}
3
3
  {% block title %}
4
4
  {% trans "Meal Type List" %}
@@ -0,0 +1,27 @@
1
+ from django.contrib import admin
2
+
3
+ from .models import Fnuser
4
+
5
+ # Register your models here.
6
+
7
+
8
+ @admin.register(Fnuser)
9
+ class FnuserAdmin(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,12 @@
1
+ from django.apps import AppConfig
2
+
3
+
4
+ class FnprofileConfig(AppConfig):
5
+ default_auto_field = "django.db.models.BigAutoField"
6
+ name = "fnprofile"
7
+
8
+ def ready(self):
9
+ import fnprofile.signals
10
+
11
+
12
+ # The end.
@@ -0,0 +1,73 @@
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 Fnuser
9
+
10
+
11
+ class FnuserLoginForm(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 FnuserForm(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
+ def __init__(self, *args, **kwargs):
40
+ super().__init__(*args, **kwargs)
41
+ self.fields["avatar"].widget.attrs.update(
42
+ {"class": "form-control-file"}
43
+ )
44
+
45
+ class Meta:
46
+ current_year = date.today().year
47
+ year_range = list(range(current_year - 100, current_year + 1))
48
+ model = Fnuser
49
+ fields = [
50
+ "username",
51
+ "phone",
52
+ "affiliation",
53
+ "superior_department",
54
+ "date_of_birth",
55
+ "gender",
56
+ "address",
57
+ "avatar",
58
+ "bio",
59
+ ]
60
+ widgets = {
61
+ "date_of_birth": forms.SelectDateWidget(
62
+ years=year_range,
63
+ attrs={"style": "width: 33.33%; display: inline-block;"},
64
+ )
65
+ }
66
+
67
+ def clean(self):
68
+ cleaned_data = super().clean()
69
+ if cleaned_data.get("password") != cleaned_data.get("password_confirm"):
70
+ raise forms.ValidationError("Passwords do not match")
71
+
72
+
73
+ # The end.
@@ -0,0 +1,213 @@
1
+ # Generated by Django 4.2.25 on 2025-10-27 13:10
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="Fnuser",
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="电话号码",
111
+ ),
112
+ ),
113
+ (
114
+ "affiliation",
115
+ models.CharField(
116
+ blank=True,
117
+ max_length=255,
118
+ null=True,
119
+ verbose_name="机构",
120
+ ),
121
+ ),
122
+ (
123
+ "superior_department",
124
+ models.CharField(
125
+ blank=True,
126
+ max_length=255,
127
+ null=True,
128
+ verbose_name="上级机构",
129
+ ),
130
+ ),
131
+ (
132
+ "date_of_birth",
133
+ models.DateField(
134
+ blank=True, null=True, verbose_name="生日"
135
+ ),
136
+ ),
137
+ (
138
+ "gender",
139
+ models.CharField(
140
+ choices=[("M", "男"), ("F", "女"), ("U", "--")],
141
+ default="U",
142
+ max_length=1,
143
+ verbose_name="性别",
144
+ ),
145
+ ),
146
+ (
147
+ "address",
148
+ models.CharField(
149
+ blank=True,
150
+ max_length=255,
151
+ null=True,
152
+ verbose_name="地址",
153
+ ),
154
+ ),
155
+ (
156
+ "avatar",
157
+ models.ImageField(
158
+ blank=True,
159
+ null=True,
160
+ upload_to="avatars/",
161
+ verbose_name="头像",
162
+ ),
163
+ ),
164
+ (
165
+ "bio",
166
+ models.TextField(
167
+ blank=True, max_length=512, verbose_name="个人简介"
168
+ ),
169
+ ),
170
+ (
171
+ "created_at",
172
+ models.DateTimeField(
173
+ auto_now_add=True, null=True, verbose_name="创建时间"
174
+ ),
175
+ ),
176
+ (
177
+ "updated_at",
178
+ models.DateTimeField(
179
+ auto_now=True, null=True, verbose_name="更新时间"
180
+ ),
181
+ ),
182
+ (
183
+ "groups",
184
+ models.ManyToManyField(
185
+ blank=True,
186
+ help_text="The groups this user belongs to.",
187
+ related_name="fn_user_groups",
188
+ related_query_name="fn_user",
189
+ to="auth.group",
190
+ verbose_name="groups",
191
+ ),
192
+ ),
193
+ (
194
+ "user_permissions",
195
+ models.ManyToManyField(
196
+ blank=True,
197
+ help_text="这个用户的特定权限。",
198
+ related_name="fn_user_permissions",
199
+ related_query_name="fn_user",
200
+ to="auth.permission",
201
+ verbose_name="user permissions",
202
+ ),
203
+ ),
204
+ ],
205
+ options={
206
+ "verbose_name": "User Information",
207
+ "verbose_name_plural": "User Information",
208
+ },
209
+ managers=[
210
+ ("objects", django.contrib.auth.models.UserManager()),
211
+ ],
212
+ ),
213
+ ]
@@ -0,0 +1,42 @@
1
+ # Generated by Django 4.2.25 on 2025-10-26 14:35
2
+
3
+ from django.db import migrations
4
+
5
+
6
+ def migrate_data_forward(apps, schema_editor):
7
+ profiles_profile_model = apps.get_model("profiles", "Profile")
8
+ fnprofile_fnuser_model = apps.get_model("fnprofile", "Fnuser")
9
+
10
+ for profile in profiles_profile_model.objects.all():
11
+ fnprofile_fnuser_model.objects.create(
12
+ phone=profile.phone,
13
+ affiliation=profile.affiliation,
14
+ superior_department=profile.superior_department,
15
+ date_of_birth=profile.date_of_birth,
16
+ gender=profile.gender,
17
+ address=profile.address,
18
+ avatar=profile.avatar,
19
+ bio=profile.bio,
20
+ password=profile.password,
21
+ username=profile.username,
22
+ id=profile.id,
23
+ )
24
+
25
+
26
+ def migrate_data_backward(apps, schema_editor):
27
+ fnprofile_fnuser_model = apps.get_model("fnprofile", "Fnuser")
28
+ fnprofile_fnuser_model.objects.all().delete()
29
+
30
+
31
+ class Migration(migrations.Migration):
32
+
33
+ dependencies = [
34
+ ("fnprofile", "0001_initial"),
35
+ ]
36
+
37
+ operations = [
38
+ migrations.RunPython(
39
+ code=migrate_data_forward,
40
+ reverse_code=migrate_data_backward,
41
+ ),
42
+ ]
@@ -0,0 +1,45 @@
1
+ # Generated by Django 4.2.25 on 2025-10-27 13:34
2
+
3
+ from django.db import migrations, models
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+
8
+ dependencies = [
9
+ ("auth", "0012_alter_user_first_name_max_length"),
10
+ ("fnprofile", "0002_auto_20251026_2235"),
11
+ ]
12
+
13
+ operations = [
14
+ migrations.AlterModelOptions(
15
+ name="fnuser",
16
+ options={
17
+ "verbose_name": "用户信息",
18
+ "verbose_name_plural": "用户信息",
19
+ },
20
+ ),
21
+ migrations.AlterField(
22
+ model_name="fnuser",
23
+ name="groups",
24
+ field=models.ManyToManyField(
25
+ blank=True,
26
+ help_text="这个用户所属的组。",
27
+ related_name="fn_user_groups",
28
+ related_query_name="fn_user",
29
+ to="auth.group",
30
+ verbose_name="groups",
31
+ ),
32
+ ),
33
+ migrations.AlterField(
34
+ model_name="fnuser",
35
+ name="user_permissions",
36
+ field=models.ManyToManyField(
37
+ blank=True,
38
+ help_text="给这个用户指定权限。",
39
+ related_name="fn_user_permissions",
40
+ related_query_name="fn_user",
41
+ to="auth.permission",
42
+ verbose_name="user permissions",
43
+ ),
44
+ ),
45
+ ]