mirror of
https://github.com/lemeow125/StudE-Backend.git
synced 2024-11-17 06:19:24 +08:00
Merge pull request #2 from lemeow125/feature/geofencing
Feature/geofencing
This commit is contained in:
commit
7d47cf79d9
66 changed files with 1331 additions and 498 deletions
5
Pipfile
5
Pipfile
|
@ -11,6 +11,11 @@ djoser = "*"
|
|||
pillow = "*"
|
||||
whitenoise = "*"
|
||||
djangochannelsrestframework = "*"
|
||||
daphne = "*"
|
||||
psycopg2 = "*"
|
||||
gdal = {path = "./packages/GDAL-3.4.3-cp311-cp311-win_amd64.whl"}
|
||||
django-leaflet = "*"
|
||||
django-extra-fields = "*"
|
||||
|
||||
[dev-packages]
|
||||
|
||||
|
|
551
Pipfile.lock
generated
551
Pipfile.lock
generated
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "231f11224ec1ef1ad1406ac5644ebcdfac020af9478f407d577553bb05c637df"
|
||||
"sha256": "975af7eaaedebb1c31a1828fdf307574edc293e0de15ecfd9cf7107f98d642f5"
|
||||
},
|
||||
"pipfile-spec": 6,
|
||||
"requires": {
|
||||
|
@ -24,6 +24,28 @@
|
|||
"markers": "python_version >= '3.7'",
|
||||
"version": "==3.7.2"
|
||||
},
|
||||
"attrs": {
|
||||
"hashes": [
|
||||
"sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04",
|
||||
"sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==23.1.0"
|
||||
},
|
||||
"autobahn": {
|
||||
"hashes": [
|
||||
"sha256:ec9421c52a2103364d1ef0468036e6019ee84f71721e86b36fe19ad6966c1181"
|
||||
],
|
||||
"markers": "python_version >= '3.9'",
|
||||
"version": "==23.6.2"
|
||||
},
|
||||
"automat": {
|
||||
"hashes": [
|
||||
"sha256:c3164f8742b9dc440f3682482d32aaff7bb53f71740dd018533f9de286b64180",
|
||||
"sha256:e56beb84edad19dcc11d30e8d9b895f75deeb5ef5e96b84a467066b3b84bb04e"
|
||||
],
|
||||
"version": "==22.10.0"
|
||||
},
|
||||
"certifi": {
|
||||
"hashes": [
|
||||
"sha256:0f0d56dc5a6ad56fd4ba36484d6cc34451e1c6548c61daad8c320169f91eddc7",
|
||||
|
@ -111,109 +133,128 @@
|
|||
},
|
||||
"charset-normalizer": {
|
||||
"hashes": [
|
||||
"sha256:04afa6387e2b282cf78ff3dbce20f0cc071c12dc8f685bd40960cc68644cfea6",
|
||||
"sha256:04eefcee095f58eaabe6dc3cc2262f3bcd776d2c67005880894f447b3f2cb9c1",
|
||||
"sha256:0be65ccf618c1e7ac9b849c315cc2e8a8751d9cfdaa43027d4f6624bd587ab7e",
|
||||
"sha256:0c95f12b74681e9ae127728f7e5409cbbef9cd914d5896ef238cc779b8152373",
|
||||
"sha256:0ca564606d2caafb0abe6d1b5311c2649e8071eb241b2d64e75a0d0065107e62",
|
||||
"sha256:10c93628d7497c81686e8e5e557aafa78f230cd9e77dd0c40032ef90c18f2230",
|
||||
"sha256:11d117e6c63e8f495412d37e7dc2e2fff09c34b2d09dbe2bee3c6229577818be",
|
||||
"sha256:11d3bcb7be35e7b1bba2c23beedac81ee893ac9871d0ba79effc7fc01167db6c",
|
||||
"sha256:12a2b561af122e3d94cdb97fe6fb2bb2b82cef0cdca131646fdb940a1eda04f0",
|
||||
"sha256:12d1a39aa6b8c6f6248bb54550efcc1c38ce0d8096a146638fd4738e42284448",
|
||||
"sha256:1435ae15108b1cb6fffbcea2af3d468683b7afed0169ad718451f8db5d1aff6f",
|
||||
"sha256:1c60b9c202d00052183c9be85e5eaf18a4ada0a47d188a83c8f5c5b23252f649",
|
||||
"sha256:1e8fcdd8f672a1c4fc8d0bd3a2b576b152d2a349782d1eb0f6b8e52e9954731d",
|
||||
"sha256:20064ead0717cf9a73a6d1e779b23d149b53daf971169289ed2ed43a71e8d3b0",
|
||||
"sha256:21fa558996782fc226b529fdd2ed7866c2c6ec91cee82735c98a197fae39f706",
|
||||
"sha256:22908891a380d50738e1f978667536f6c6b526a2064156203d418f4856d6e86a",
|
||||
"sha256:3160a0fd9754aab7d47f95a6b63ab355388d890163eb03b2d2b87ab0a30cfa59",
|
||||
"sha256:322102cdf1ab682ecc7d9b1c5eed4ec59657a65e1c146a0da342b78f4112db23",
|
||||
"sha256:34e0a2f9c370eb95597aae63bf85eb5e96826d81e3dcf88b8886012906f509b5",
|
||||
"sha256:3573d376454d956553c356df45bb824262c397c6e26ce43e8203c4c540ee0acb",
|
||||
"sha256:3747443b6a904001473370d7810aa19c3a180ccd52a7157aacc264a5ac79265e",
|
||||
"sha256:38e812a197bf8e71a59fe55b757a84c1f946d0ac114acafaafaf21667a7e169e",
|
||||
"sha256:3a06f32c9634a8705f4ca9946d667609f52cf130d5548881401f1eb2c39b1e2c",
|
||||
"sha256:3a5fc78f9e3f501a1614a98f7c54d3969f3ad9bba8ba3d9b438c3bc5d047dd28",
|
||||
"sha256:3d9098b479e78c85080c98e1e35ff40b4a31d8953102bb0fd7d1b6f8a2111a3d",
|
||||
"sha256:3dc5b6a8ecfdc5748a7e429782598e4f17ef378e3e272eeb1340ea57c9109f41",
|
||||
"sha256:4155b51ae05ed47199dc5b2a4e62abccb274cee6b01da5b895099b61b1982974",
|
||||
"sha256:49919f8400b5e49e961f320c735388ee686a62327e773fa5b3ce6721f7e785ce",
|
||||
"sha256:53d0a3fa5f8af98a1e261de6a3943ca631c526635eb5817a87a59d9a57ebf48f",
|
||||
"sha256:5f008525e02908b20e04707a4f704cd286d94718f48bb33edddc7d7b584dddc1",
|
||||
"sha256:628c985afb2c7d27a4800bfb609e03985aaecb42f955049957814e0491d4006d",
|
||||
"sha256:65ed923f84a6844de5fd29726b888e58c62820e0769b76565480e1fdc3d062f8",
|
||||
"sha256:6734e606355834f13445b6adc38b53c0fd45f1a56a9ba06c2058f86893ae8017",
|
||||
"sha256:6baf0baf0d5d265fa7944feb9f7451cc316bfe30e8df1a61b1bb08577c554f31",
|
||||
"sha256:6f4f4668e1831850ebcc2fd0b1cd11721947b6dc7c00bf1c6bd3c929ae14f2c7",
|
||||
"sha256:6f5c2e7bc8a4bf7c426599765b1bd33217ec84023033672c1e9a8b35eaeaaaf8",
|
||||
"sha256:6f6c7a8a57e9405cad7485f4c9d3172ae486cfef1344b5ddd8e5239582d7355e",
|
||||
"sha256:7381c66e0561c5757ffe616af869b916c8b4e42b367ab29fedc98481d1e74e14",
|
||||
"sha256:73dc03a6a7e30b7edc5b01b601e53e7fc924b04e1835e8e407c12c037e81adbd",
|
||||
"sha256:74db0052d985cf37fa111828d0dd230776ac99c740e1a758ad99094be4f1803d",
|
||||
"sha256:75f2568b4189dda1c567339b48cba4ac7384accb9c2a7ed655cd86b04055c795",
|
||||
"sha256:78cacd03e79d009d95635e7d6ff12c21eb89b894c354bd2b2ed0b4763373693b",
|
||||
"sha256:80d1543d58bd3d6c271b66abf454d437a438dff01c3e62fdbcd68f2a11310d4b",
|
||||
"sha256:830d2948a5ec37c386d3170c483063798d7879037492540f10a475e3fd6f244b",
|
||||
"sha256:891cf9b48776b5c61c700b55a598621fdb7b1e301a550365571e9624f270c203",
|
||||
"sha256:8f25e17ab3039b05f762b0a55ae0b3632b2e073d9c8fc88e89aca31a6198e88f",
|
||||
"sha256:9a3267620866c9d17b959a84dd0bd2d45719b817245e49371ead79ed4f710d19",
|
||||
"sha256:a04f86f41a8916fe45ac5024ec477f41f886b3c435da2d4e3d2709b22ab02af1",
|
||||
"sha256:aaf53a6cebad0eae578f062c7d462155eada9c172bd8c4d250b8c1d8eb7f916a",
|
||||
"sha256:abc1185d79f47c0a7aaf7e2412a0eb2c03b724581139193d2d82b3ad8cbb00ac",
|
||||
"sha256:ac0aa6cd53ab9a31d397f8303f92c42f534693528fafbdb997c82bae6e477ad9",
|
||||
"sha256:ac3775e3311661d4adace3697a52ac0bab17edd166087d493b52d4f4f553f9f0",
|
||||
"sha256:b06f0d3bf045158d2fb8837c5785fe9ff9b8c93358be64461a1089f5da983137",
|
||||
"sha256:b116502087ce8a6b7a5f1814568ccbd0e9f6cfd99948aa59b0e241dc57cf739f",
|
||||
"sha256:b82fab78e0b1329e183a65260581de4375f619167478dddab510c6c6fb04d9b6",
|
||||
"sha256:bd7163182133c0c7701b25e604cf1611c0d87712e56e88e7ee5d72deab3e76b5",
|
||||
"sha256:c36bcbc0d5174a80d6cccf43a0ecaca44e81d25be4b7f90f0ed7bcfbb5a00909",
|
||||
"sha256:c3af8e0f07399d3176b179f2e2634c3ce9c1301379a6b8c9c9aeecd481da494f",
|
||||
"sha256:c84132a54c750fda57729d1e2599bb598f5fa0344085dbde5003ba429a4798c0",
|
||||
"sha256:cb7b2ab0188829593b9de646545175547a70d9a6e2b63bf2cd87a0a391599324",
|
||||
"sha256:cca4def576f47a09a943666b8f829606bcb17e2bc2d5911a46c8f8da45f56755",
|
||||
"sha256:cf6511efa4801b9b38dc5546d7547d5b5c6ef4b081c60b23e4d941d0eba9cbeb",
|
||||
"sha256:d16fd5252f883eb074ca55cb622bc0bee49b979ae4e8639fff6ca3ff44f9f854",
|
||||
"sha256:d2686f91611f9e17f4548dbf050e75b079bbc2a82be565832bc8ea9047b61c8c",
|
||||
"sha256:d7fc3fca01da18fbabe4625d64bb612b533533ed10045a2ac3dd194bfa656b60",
|
||||
"sha256:dd5653e67b149503c68c4018bf07e42eeed6b4e956b24c00ccdf93ac79cdff84",
|
||||
"sha256:de5695a6f1d8340b12a5d6d4484290ee74d61e467c39ff03b39e30df62cf83a0",
|
||||
"sha256:e0ac8959c929593fee38da1c2b64ee9778733cdf03c482c9ff1d508b6b593b2b",
|
||||
"sha256:e1b25e3ad6c909f398df8921780d6a3d120d8c09466720226fc621605b6f92b1",
|
||||
"sha256:e633940f28c1e913615fd624fcdd72fdba807bf53ea6925d6a588e84e1151531",
|
||||
"sha256:e89df2958e5159b811af9ff0f92614dabf4ff617c03a4c1c6ff53bf1c399e0e1",
|
||||
"sha256:ea9f9c6034ea2d93d9147818f17c2a0860d41b71c38b9ce4d55f21b6f9165a11",
|
||||
"sha256:f645caaf0008bacf349875a974220f1f1da349c5dbe7c4ec93048cdc785a3326",
|
||||
"sha256:f8303414c7b03f794347ad062c0516cee0e15f7a612abd0ce1e25caf6ceb47df",
|
||||
"sha256:fca62a8301b605b954ad2e9c3666f9d97f63872aa4efcae5492baca2056b74ab"
|
||||
"sha256:04e57ab9fbf9607b77f7d057974694b4f6b142da9ed4a199859d9d4d5c63fe96",
|
||||
"sha256:09393e1b2a9461950b1c9a45d5fd251dc7c6f228acab64da1c9c0165d9c7765c",
|
||||
"sha256:0b87549028f680ca955556e3bd57013ab47474c3124dc069faa0b6545b6c9710",
|
||||
"sha256:1000fba1057b92a65daec275aec30586c3de2401ccdcd41f8a5c1e2c87078706",
|
||||
"sha256:1249cbbf3d3b04902ff081ffbb33ce3377fa6e4c7356f759f3cd076cc138d020",
|
||||
"sha256:1920d4ff15ce893210c1f0c0e9d19bfbecb7983c76b33f046c13a8ffbd570252",
|
||||
"sha256:193cbc708ea3aca45e7221ae58f0fd63f933753a9bfb498a3b474878f12caaad",
|
||||
"sha256:1a100c6d595a7f316f1b6f01d20815d916e75ff98c27a01ae817439ea7726329",
|
||||
"sha256:1f30b48dd7fa1474554b0b0f3fdfdd4c13b5c737a3c6284d3cdc424ec0ffff3a",
|
||||
"sha256:203f0c8871d5a7987be20c72442488a0b8cfd0f43b7973771640fc593f56321f",
|
||||
"sha256:246de67b99b6851627d945db38147d1b209a899311b1305dd84916f2b88526c6",
|
||||
"sha256:2dee8e57f052ef5353cf608e0b4c871aee320dd1b87d351c28764fc0ca55f9f4",
|
||||
"sha256:2efb1bd13885392adfda4614c33d3b68dee4921fd0ac1d3988f8cbb7d589e72a",
|
||||
"sha256:2f4ac36d8e2b4cc1aa71df3dd84ff8efbe3bfb97ac41242fbcfc053c67434f46",
|
||||
"sha256:3170c9399da12c9dc66366e9d14da8bf7147e1e9d9ea566067bbce7bb74bd9c2",
|
||||
"sha256:3b1613dd5aee995ec6d4c69f00378bbd07614702a315a2cf6c1d21461fe17c23",
|
||||
"sha256:3bb3d25a8e6c0aedd251753a79ae98a093c7e7b471faa3aa9a93a81431987ace",
|
||||
"sha256:3bb7fda7260735efe66d5107fb7e6af6a7c04c7fce9b2514e04b7a74b06bf5dd",
|
||||
"sha256:41b25eaa7d15909cf3ac4c96088c1f266a9a93ec44f87f1d13d4a0e86c81b982",
|
||||
"sha256:45de3f87179c1823e6d9e32156fb14c1927fcc9aba21433f088fdfb555b77c10",
|
||||
"sha256:46fb8c61d794b78ec7134a715a3e564aafc8f6b5e338417cb19fe9f57a5a9bf2",
|
||||
"sha256:48021783bdf96e3d6de03a6e39a1171ed5bd7e8bb93fc84cc649d11490f87cea",
|
||||
"sha256:4957669ef390f0e6719db3613ab3a7631e68424604a7b448f079bee145da6e09",
|
||||
"sha256:5e86d77b090dbddbe78867a0275cb4df08ea195e660f1f7f13435a4649e954e5",
|
||||
"sha256:6339d047dab2780cc6220f46306628e04d9750f02f983ddb37439ca47ced7149",
|
||||
"sha256:681eb3d7e02e3c3655d1b16059fbfb605ac464c834a0c629048a30fad2b27489",
|
||||
"sha256:6c409c0deba34f147f77efaa67b8e4bb83d2f11c8806405f76397ae5b8c0d1c9",
|
||||
"sha256:7095f6fbfaa55defb6b733cfeb14efaae7a29f0b59d8cf213be4e7ca0b857b80",
|
||||
"sha256:70c610f6cbe4b9fce272c407dd9d07e33e6bf7b4aa1b7ffb6f6ded8e634e3592",
|
||||
"sha256:72814c01533f51d68702802d74f77ea026b5ec52793c791e2da806a3844a46c3",
|
||||
"sha256:7a4826ad2bd6b07ca615c74ab91f32f6c96d08f6fcc3902ceeedaec8cdc3bcd6",
|
||||
"sha256:7c70087bfee18a42b4040bb9ec1ca15a08242cf5867c58726530bdf3945672ed",
|
||||
"sha256:855eafa5d5a2034b4621c74925d89c5efef61418570e5ef9b37717d9c796419c",
|
||||
"sha256:8700f06d0ce6f128de3ccdbc1acaea1ee264d2caa9ca05daaf492fde7c2a7200",
|
||||
"sha256:89f1b185a01fe560bc8ae5f619e924407efca2191b56ce749ec84982fc59a32a",
|
||||
"sha256:8b2c760cfc7042b27ebdb4a43a4453bd829a5742503599144d54a032c5dc7e9e",
|
||||
"sha256:8c2f5e83493748286002f9369f3e6607c565a6a90425a3a1fef5ae32a36d749d",
|
||||
"sha256:8e098148dd37b4ce3baca71fb394c81dc5d9c7728c95df695d2dca218edf40e6",
|
||||
"sha256:94aea8eff76ee6d1cdacb07dd2123a68283cb5569e0250feab1240058f53b623",
|
||||
"sha256:95eb302ff792e12aba9a8b8f8474ab229a83c103d74a750ec0bd1c1eea32e669",
|
||||
"sha256:9bd9b3b31adcb054116447ea22caa61a285d92e94d710aa5ec97992ff5eb7cf3",
|
||||
"sha256:9e608aafdb55eb9f255034709e20d5a83b6d60c054df0802fa9c9883d0a937aa",
|
||||
"sha256:a103b3a7069b62f5d4890ae1b8f0597618f628b286b03d4bc9195230b154bfa9",
|
||||
"sha256:a386ebe437176aab38c041de1260cd3ea459c6ce5263594399880bbc398225b2",
|
||||
"sha256:a38856a971c602f98472050165cea2cdc97709240373041b69030be15047691f",
|
||||
"sha256:a401b4598e5d3f4a9a811f3daf42ee2291790c7f9d74b18d75d6e21dda98a1a1",
|
||||
"sha256:a7647ebdfb9682b7bb97e2a5e7cb6ae735b1c25008a70b906aecca294ee96cf4",
|
||||
"sha256:aaf63899c94de41fe3cf934601b0f7ccb6b428c6e4eeb80da72c58eab077b19a",
|
||||
"sha256:b0dac0ff919ba34d4df1b6131f59ce95b08b9065233446be7e459f95554c0dc8",
|
||||
"sha256:baacc6aee0b2ef6f3d308e197b5d7a81c0e70b06beae1f1fcacffdbd124fe0e3",
|
||||
"sha256:bf420121d4c8dce6b889f0e8e4ec0ca34b7f40186203f06a946fa0276ba54029",
|
||||
"sha256:c04a46716adde8d927adb9457bbe39cf473e1e2c2f5d0a16ceb837e5d841ad4f",
|
||||
"sha256:c0b21078a4b56965e2b12f247467b234734491897e99c1d51cee628da9786959",
|
||||
"sha256:c1c76a1743432b4b60ab3358c937a3fe1341c828ae6194108a94c69028247f22",
|
||||
"sha256:c4983bf937209c57240cff65906b18bb35e64ae872da6a0db937d7b4af845dd7",
|
||||
"sha256:c4fb39a81950ec280984b3a44f5bd12819953dc5fa3a7e6fa7a80db5ee853952",
|
||||
"sha256:c57921cda3a80d0f2b8aec7e25c8aa14479ea92b5b51b6876d975d925a2ea346",
|
||||
"sha256:c8063cf17b19661471ecbdb3df1c84f24ad2e389e326ccaf89e3fb2484d8dd7e",
|
||||
"sha256:ccd16eb18a849fd8dcb23e23380e2f0a354e8daa0c984b8a732d9cfaba3a776d",
|
||||
"sha256:cd6dbe0238f7743d0efe563ab46294f54f9bc8f4b9bcf57c3c666cc5bc9d1299",
|
||||
"sha256:d62e51710986674142526ab9f78663ca2b0726066ae26b78b22e0f5e571238dd",
|
||||
"sha256:db901e2ac34c931d73054d9797383d0f8009991e723dab15109740a63e7f902a",
|
||||
"sha256:e03b8895a6990c9ab2cdcd0f2fe44088ca1c65ae592b8f795c3294af00a461c3",
|
||||
"sha256:e1c8a2f4c69e08e89632defbfabec2feb8a8d99edc9f89ce33c4b9e36ab63037",
|
||||
"sha256:e4b749b9cc6ee664a3300bb3a273c1ca8068c46be705b6c31cf5d276f8628a94",
|
||||
"sha256:e6a5bf2cba5ae1bb80b154ed68a3cfa2fa00fde979a7f50d6598d3e17d9ac20c",
|
||||
"sha256:e857a2232ba53ae940d3456f7533ce6ca98b81917d47adc3c7fd55dad8fab858",
|
||||
"sha256:ee4006268ed33370957f55bf2e6f4d263eaf4dc3cfc473d1d90baff6ed36ce4a",
|
||||
"sha256:eef9df1eefada2c09a5e7a40991b9fc6ac6ef20b1372abd48d2794a316dc0449",
|
||||
"sha256:f058f6963fd82eb143c692cecdc89e075fa0828db2e5b291070485390b2f1c9c",
|
||||
"sha256:f25c229a6ba38a35ae6e25ca1264621cc25d4d38dca2942a7fce0b67a4efe918",
|
||||
"sha256:f2a1d0fd4242bd8643ce6f98927cf9c04540af6efa92323e9d3124f57727bfc1",
|
||||
"sha256:f7560358a6811e52e9c4d142d497f1a6e10103d3a6881f18d04dbce3729c0e2c",
|
||||
"sha256:f779d3ad205f108d14e99bb3859aa7dd8e9c68874617c72354d7ecaec2a054ac",
|
||||
"sha256:f87f746ee241d30d6ed93969de31e5ffd09a2961a051e60ae6bddde9ec3583aa"
|
||||
],
|
||||
"markers": "python_full_version >= '3.7.0'",
|
||||
"version": "==3.1.0"
|
||||
"version": "==3.2.0"
|
||||
},
|
||||
"constantly": {
|
||||
"hashes": [
|
||||
"sha256:586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35",
|
||||
"sha256:dd2fa9d6b1a51a83f0d7dd76293d734046aa176e384bf6e33b7e44880eb37c5d"
|
||||
],
|
||||
"version": "==15.1.0"
|
||||
},
|
||||
"cryptography": {
|
||||
"hashes": [
|
||||
"sha256:059e348f9a3c1950937e1b5d7ba1f8e968508ab181e75fc32b879452f08356db",
|
||||
"sha256:1a5472d40c8f8e91ff7a3d8ac6dfa363d8e3138b961529c996f3e2df0c7a411a",
|
||||
"sha256:1a8e6c2de6fbbcc5e14fd27fb24414507cb3333198ea9ab1258d916f00bc3039",
|
||||
"sha256:1fee5aacc7367487b4e22484d3c7e547992ed726d14864ee33c0176ae43b0d7c",
|
||||
"sha256:5d092fdfedaec4cbbffbf98cddc915ba145313a6fdaab83c6e67f4e6c218e6f3",
|
||||
"sha256:5f0ff6e18d13a3de56f609dd1fd11470918f770c6bd5d00d632076c727d35485",
|
||||
"sha256:7bfc55a5eae8b86a287747053140ba221afc65eb06207bedf6e019b8934b477c",
|
||||
"sha256:7fa01527046ca5facdf973eef2535a27fec4cb651e4daec4d043ef63f6ecd4ca",
|
||||
"sha256:8dde71c4169ec5ccc1087bb7521d54251c016f126f922ab2dfe6649170a3b8c5",
|
||||
"sha256:8f4ab7021127a9b4323537300a2acfb450124b2def3756f64dc3a3d2160ee4b5",
|
||||
"sha256:948224d76c4b6457349d47c0c98657557f429b4e93057cf5a2f71d603e2fc3a3",
|
||||
"sha256:9a6c7a3c87d595608a39980ebaa04d5a37f94024c9f24eb7d10262b92f739ddb",
|
||||
"sha256:b46e37db3cc267b4dea1f56da7346c9727e1209aa98487179ee8ebed09d21e43",
|
||||
"sha256:b4ceb5324b998ce2003bc17d519080b4ec8d5b7b70794cbd2836101406a9be31",
|
||||
"sha256:cb33ccf15e89f7ed89b235cff9d49e2e62c6c981a6061c9c8bb47ed7951190bc",
|
||||
"sha256:d198820aba55660b4d74f7b5fd1f17db3aa5eb3e6893b0a41b75e84e4f9e0e4b",
|
||||
"sha256:d34579085401d3f49762d2f7d6634d6b6c2ae1242202e860f4d26b046e3a1006",
|
||||
"sha256:eb8163f5e549a22888c18b0d53d6bb62a20510060a22fd5a995ec8a05268df8a",
|
||||
"sha256:f73bff05db2a3e5974a6fd248af2566134d8981fd7ab012e5dd4ddb1d9a70699"
|
||||
"sha256:01f1d9e537f9a15b037d5d9ee442b8c22e3ae11ce65ea1f3316a41c78756b711",
|
||||
"sha256:079347de771f9282fbfe0e0236c716686950c19dee1b76240ab09ce1624d76d7",
|
||||
"sha256:182be4171f9332b6741ee818ec27daff9fb00349f706629f5cbf417bd50e66fd",
|
||||
"sha256:192255f539d7a89f2102d07d7375b1e0a81f7478925b3bc2e0549ebf739dae0e",
|
||||
"sha256:2a034bf7d9ca894720f2ec1d8b7b5832d7e363571828037f9e0c4f18c1b58a58",
|
||||
"sha256:342f3767e25876751e14f8459ad85e77e660537ca0a066e10e75df9c9e9099f0",
|
||||
"sha256:439c3cc4c0d42fa999b83ded80a9a1fb54d53c58d6e59234cfe97f241e6c781d",
|
||||
"sha256:49c3222bb8f8e800aead2e376cbef687bc9e3cb9b58b29a261210456a7783d83",
|
||||
"sha256:674b669d5daa64206c38e507808aae49904c988fa0a71c935e7006a3e1e83831",
|
||||
"sha256:7a9a3bced53b7f09da251685224d6a260c3cb291768f54954e28f03ef14e3766",
|
||||
"sha256:7af244b012711a26196450d34f483357e42aeddb04128885d95a69bd8b14b69b",
|
||||
"sha256:7d230bf856164de164ecb615ccc14c7fc6de6906ddd5b491f3af90d3514c925c",
|
||||
"sha256:84609ade00a6ec59a89729e87a503c6e36af98ddcd566d5f3be52e29ba993182",
|
||||
"sha256:9a6673c1828db6270b76b22cc696f40cde9043eb90373da5c2f8f2158957f42f",
|
||||
"sha256:9b6d717393dbae53d4e52684ef4f022444fc1cce3c48c38cb74fca29e1f08eaa",
|
||||
"sha256:9c3fe6534d59d071ee82081ca3d71eed3210f76ebd0361798c74abc2bcf347d4",
|
||||
"sha256:a719399b99377b218dac6cf547b6ec54e6ef20207b6165126a280b0ce97e0d2a",
|
||||
"sha256:b332cba64d99a70c1e0836902720887fb4529ea49ea7f5462cf6640e095e11d2",
|
||||
"sha256:d124682c7a23c9764e54ca9ab5b308b14b18eba02722b8659fb238546de83a76",
|
||||
"sha256:d73f419a56d74fef257955f51b18d046f3506270a5fd2ac5febbfa259d6c0fa5",
|
||||
"sha256:f0dc40e6f7aa37af01aba07277d3d64d5a03dc66d682097541ec4da03cc140ee",
|
||||
"sha256:f14ad275364c8b4e525d018f6716537ae7b6d369c094805cae45300847e0894f",
|
||||
"sha256:f772610fe364372de33d76edcd313636a25684edb94cee53fd790195f5989d14"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==41.0.1"
|
||||
"version": "==41.0.2"
|
||||
},
|
||||
"daphne": {
|
||||
"hashes": [
|
||||
"sha256:a288ece46012b6b719c37150be67c69ebfca0793a8521bf821533bad983179b2",
|
||||
"sha256:cce9afc8f49a4f15d4270b8cfb0e0fe811b770a5cc795474e97e4da287497666"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==4.0.0"
|
||||
},
|
||||
"defusedxml": {
|
||||
"hashes": [
|
||||
|
@ -225,11 +266,26 @@
|
|||
},
|
||||
"django": {
|
||||
"hashes": [
|
||||
"sha256:2a6b6fbff5b59dd07bef10bcb019bee2ea97a30b2a656d51346596724324badf",
|
||||
"sha256:672b3fa81e1f853bb58be1b51754108ab4ffa12a77c06db86aa8df9ed0c46fe5"
|
||||
"sha256:45a747e1c5b3d6df1b141b1481e193b033fd1fdbda3ff52677dc81afdaacbaed",
|
||||
"sha256:f7c7852a5ac5a3da5a8d5b35cc6168f31b605971441798dac845f17ca8028039"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==4.2.2"
|
||||
"version": "==4.2.3"
|
||||
},
|
||||
"django-extra-fields": {
|
||||
"hashes": [
|
||||
"sha256:2334e914b346c0a19a7765bf0ff7895c46cf35d5f40315a68418f44b7ddbb33b"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==3.0.2"
|
||||
},
|
||||
"django-leaflet": {
|
||||
"hashes": [
|
||||
"sha256:2f6dc8c7187fd22e62b6f2b7b42eed86920f81bec312aa654981ebe5bc8e0866",
|
||||
"sha256:ea35244539fe298156feafc7f1e2ce63067c8caa2ac6f8344069796b19d1ce9b"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==0.29.0"
|
||||
},
|
||||
"django-templated-mail": {
|
||||
"hashes": [
|
||||
|
@ -270,6 +326,20 @@
|
|||
"index": "pypi",
|
||||
"version": "==2.2.0"
|
||||
},
|
||||
"gdal": {
|
||||
"hashes": [
|
||||
"sha256:f78861fb5115d5c2f8cf3c52a492ff548da9e1256dc84088947379f90e77e5b6"
|
||||
],
|
||||
"path": "./packages/GDAL-3.4.3-cp311-cp311-win_amd64.whl",
|
||||
"version": "==3.4.3"
|
||||
},
|
||||
"hyperlink": {
|
||||
"hashes": [
|
||||
"sha256:427af957daa58bc909471c6c40f74c5450fa123dd093fc53efd2e91d2705a56b",
|
||||
"sha256:e6b14c37ecb73e89c77d78cdb4c2cc8f3fb59a885c5b3f819ff4ed80f25af1b4"
|
||||
],
|
||||
"version": "==21.0.0"
|
||||
},
|
||||
"idna": {
|
||||
"hashes": [
|
||||
"sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4",
|
||||
|
@ -278,6 +348,13 @@
|
|||
"markers": "python_version >= '3.5'",
|
||||
"version": "==3.4"
|
||||
},
|
||||
"incremental": {
|
||||
"hashes": [
|
||||
"sha256:912feeb5e0f7e0188e6f42241d2f450002e11bbc0937c65865045854c24c0bd0",
|
||||
"sha256:b864a1f30885ee72c5ac2835a761b8fe8aa9c28b9395cacf27286602688d3e51"
|
||||
],
|
||||
"version": "==22.10.0"
|
||||
},
|
||||
"oauthlib": {
|
||||
"hashes": [
|
||||
"sha256:8139f29aac13e25d502680e9e19963e83f16838d48a0d71c287fe40e7067fbca",
|
||||
|
@ -288,75 +365,100 @@
|
|||
},
|
||||
"pillow": {
|
||||
"hashes": [
|
||||
"sha256:07999f5834bdc404c442146942a2ecadd1cb6292f5229f4ed3b31e0a108746b1",
|
||||
"sha256:0852ddb76d85f127c135b6dd1f0bb88dbb9ee990d2cd9aa9e28526c93e794fba",
|
||||
"sha256:1781a624c229cb35a2ac31cc4a77e28cafc8900733a864870c49bfeedacd106a",
|
||||
"sha256:1e7723bd90ef94eda669a3c2c19d549874dd5badaeefabefd26053304abe5799",
|
||||
"sha256:229e2c79c00e85989a34b5981a2b67aa079fd08c903f0aaead522a1d68d79e51",
|
||||
"sha256:22baf0c3cf0c7f26e82d6e1adf118027afb325e703922c8dfc1d5d0156bb2eeb",
|
||||
"sha256:252a03f1bdddce077eff2354c3861bf437c892fb1832f75ce813ee94347aa9b5",
|
||||
"sha256:2dfaaf10b6172697b9bceb9a3bd7b951819d1ca339a5ef294d1f1ac6d7f63270",
|
||||
"sha256:322724c0032af6692456cd6ed554bb85f8149214d97398bb80613b04e33769f6",
|
||||
"sha256:35f6e77122a0c0762268216315bf239cf52b88865bba522999dc38f1c52b9b47",
|
||||
"sha256:375f6e5ee9620a271acb6820b3d1e94ffa8e741c0601db4c0c4d3cb0a9c224bf",
|
||||
"sha256:3ded42b9ad70e5f1754fb7c2e2d6465a9c842e41d178f262e08b8c85ed8a1d8e",
|
||||
"sha256:432b975c009cf649420615388561c0ce7cc31ce9b2e374db659ee4f7d57a1f8b",
|
||||
"sha256:482877592e927fd263028c105b36272398e3e1be3269efda09f6ba21fd83ec66",
|
||||
"sha256:489f8389261e5ed43ac8ff7b453162af39c3e8abd730af8363587ba64bb2e865",
|
||||
"sha256:54f7102ad31a3de5666827526e248c3530b3a33539dbda27c6843d19d72644ec",
|
||||
"sha256:560737e70cb9c6255d6dcba3de6578a9e2ec4b573659943a5e7e4af13f298f5c",
|
||||
"sha256:5671583eab84af046a397d6d0ba25343c00cd50bce03787948e0fff01d4fd9b1",
|
||||
"sha256:5ba1b81ee69573fe7124881762bb4cd2e4b6ed9dd28c9c60a632902fe8db8b38",
|
||||
"sha256:5d4ebf8e1db4441a55c509c4baa7a0587a0210f7cd25fcfe74dbbce7a4bd1906",
|
||||
"sha256:60037a8db8750e474af7ffc9faa9b5859e6c6d0a50e55c45576bf28be7419705",
|
||||
"sha256:608488bdcbdb4ba7837461442b90ea6f3079397ddc968c31265c1e056964f1ef",
|
||||
"sha256:6608ff3bf781eee0cd14d0901a2b9cc3d3834516532e3bd673a0a204dc8615fc",
|
||||
"sha256:662da1f3f89a302cc22faa9f14a262c2e3951f9dbc9617609a47521c69dd9f8f",
|
||||
"sha256:7002d0797a3e4193c7cdee3198d7c14f92c0836d6b4a3f3046a64bd1ce8df2bf",
|
||||
"sha256:763782b2e03e45e2c77d7779875f4432e25121ef002a41829d8868700d119392",
|
||||
"sha256:77165c4a5e7d5a284f10a6efaa39a0ae8ba839da344f20b111d62cc932fa4e5d",
|
||||
"sha256:7c9af5a3b406a50e313467e3565fc99929717f780164fe6fbb7704edba0cebbe",
|
||||
"sha256:7ec6f6ce99dab90b52da21cf0dc519e21095e332ff3b399a357c187b1a5eee32",
|
||||
"sha256:833b86a98e0ede388fa29363159c9b1a294b0905b5128baf01db683672f230f5",
|
||||
"sha256:84a6f19ce086c1bf894644b43cd129702f781ba5751ca8572f08aa40ef0ab7b7",
|
||||
"sha256:8507eda3cd0608a1f94f58c64817e83ec12fa93a9436938b191b80d9e4c0fc44",
|
||||
"sha256:85ec677246533e27770b0de5cf0f9d6e4ec0c212a1f89dfc941b64b21226009d",
|
||||
"sha256:8aca1152d93dcc27dc55395604dcfc55bed5f25ef4c98716a928bacba90d33a3",
|
||||
"sha256:8d935f924bbab8f0a9a28404422da8af4904e36d5c33fc6f677e4c4485515625",
|
||||
"sha256:8f36397bf3f7d7c6a3abdea815ecf6fd14e7fcd4418ab24bae01008d8d8ca15e",
|
||||
"sha256:91ec6fe47b5eb5a9968c79ad9ed78c342b1f97a091677ba0e012701add857829",
|
||||
"sha256:965e4a05ef364e7b973dd17fc765f42233415974d773e82144c9bbaaaea5d089",
|
||||
"sha256:96e88745a55b88a7c64fa49bceff363a1a27d9a64e04019c2281049444a571e3",
|
||||
"sha256:99eb6cafb6ba90e436684e08dad8be1637efb71c4f2180ee6b8f940739406e78",
|
||||
"sha256:9adf58f5d64e474bed00d69bcd86ec4bcaa4123bfa70a65ce72e424bfb88ed96",
|
||||
"sha256:9b1af95c3a967bf1da94f253e56b6286b50af23392a886720f563c547e48e964",
|
||||
"sha256:a0aa9417994d91301056f3d0038af1199eb7adc86e646a36b9e050b06f526597",
|
||||
"sha256:a0f9bb6c80e6efcde93ffc51256d5cfb2155ff8f78292f074f60f9e70b942d99",
|
||||
"sha256:a127ae76092974abfbfa38ca2d12cbeddcdeac0fb71f9627cc1135bedaf9d51a",
|
||||
"sha256:aaf305d6d40bd9632198c766fb64f0c1a83ca5b667f16c1e79e1661ab5060140",
|
||||
"sha256:aca1c196f407ec7cf04dcbb15d19a43c507a81f7ffc45b690899d6a76ac9fda7",
|
||||
"sha256:ace6ca218308447b9077c14ea4ef381ba0b67ee78d64046b3f19cf4e1139ad16",
|
||||
"sha256:b416f03d37d27290cb93597335a2f85ed446731200705b22bb927405320de903",
|
||||
"sha256:bf548479d336726d7a0eceb6e767e179fbde37833ae42794602631a070d630f1",
|
||||
"sha256:c1170d6b195555644f0616fd6ed929dfcf6333b8675fcca044ae5ab110ded296",
|
||||
"sha256:c380b27d041209b849ed246b111b7c166ba36d7933ec6e41175fd15ab9eb1572",
|
||||
"sha256:c446d2245ba29820d405315083d55299a796695d747efceb5717a8b450324115",
|
||||
"sha256:c830a02caeb789633863b466b9de10c015bded434deb3ec87c768e53752ad22a",
|
||||
"sha256:cb841572862f629b99725ebaec3287fc6d275be9b14443ea746c1dd325053cbd",
|
||||
"sha256:cfa4561277f677ecf651e2b22dc43e8f5368b74a25a8f7d1d4a3a243e573f2d4",
|
||||
"sha256:cfcc2c53c06f2ccb8976fb5c71d448bdd0a07d26d8e07e321c103416444c7ad1",
|
||||
"sha256:d3c6b54e304c60c4181da1c9dadf83e4a54fd266a99c70ba646a9baa626819eb",
|
||||
"sha256:d3d403753c9d5adc04d4694d35cf0391f0f3d57c8e0030aac09d7678fa8030aa",
|
||||
"sha256:d9c206c29b46cfd343ea7cdfe1232443072bbb270d6a46f59c259460db76779a",
|
||||
"sha256:e49eb4e95ff6fd7c0c402508894b1ef0e01b99a44320ba7d8ecbabefddcc5569",
|
||||
"sha256:f8286396b351785801a976b1e85ea88e937712ee2c3ac653710a4a57a8da5d9c",
|
||||
"sha256:f8fc330c3370a81bbf3f88557097d1ea26cd8b019d6433aa59f71195f5ddebbf",
|
||||
"sha256:fbd359831c1657d69bb81f0db962905ee05e5e9451913b18b831febfe0519082",
|
||||
"sha256:fe7e1c262d3392afcf5071df9afa574544f28eac825284596ac6db56e6d11062",
|
||||
"sha256:fed1e1cf6a42577953abbe8e6cf2fe2f566daebde7c34724ec8803c4c0cda579"
|
||||
"sha256:00e65f5e822decd501e374b0650146063fbb30a7264b4d2744bdd7b913e0cab5",
|
||||
"sha256:040586f7d37b34547153fa383f7f9aed68b738992380ac911447bb78f2abe530",
|
||||
"sha256:0b6eb5502f45a60a3f411c63187db83a3d3107887ad0d036c13ce836f8a36f1d",
|
||||
"sha256:1ce91b6ec08d866b14413d3f0bbdea7e24dfdc8e59f562bb77bc3fe60b6144ca",
|
||||
"sha256:1f62406a884ae75fb2f818694469519fb685cc7eaff05d3451a9ebe55c646891",
|
||||
"sha256:22c10cc517668d44b211717fd9775799ccec4124b9a7f7b3635fc5386e584992",
|
||||
"sha256:3400aae60685b06bb96f99a21e1ada7bc7a413d5f49bce739828ecd9391bb8f7",
|
||||
"sha256:349930d6e9c685c089284b013478d6f76e3a534e36ddfa912cde493f235372f3",
|
||||
"sha256:368ab3dfb5f49e312231b6f27b8820c823652b7cd29cfbd34090565a015e99ba",
|
||||
"sha256:38250a349b6b390ee6047a62c086d3817ac69022c127f8a5dc058c31ccef17f3",
|
||||
"sha256:3a684105f7c32488f7153905a4e3015a3b6c7182e106fe3c37fbb5ef3e6994c3",
|
||||
"sha256:3a82c40d706d9aa9734289740ce26460a11aeec2d9c79b7af87bb35f0073c12f",
|
||||
"sha256:3b08d4cc24f471b2c8ca24ec060abf4bebc6b144cb89cba638c720546b1cf538",
|
||||
"sha256:3ed64f9ca2f0a95411e88a4efbd7a29e5ce2cea36072c53dd9d26d9c76f753b3",
|
||||
"sha256:3f07ea8d2f827d7d2a49ecf1639ec02d75ffd1b88dcc5b3a61bbb37a8759ad8d",
|
||||
"sha256:520f2a520dc040512699f20fa1c363eed506e94248d71f85412b625026f6142c",
|
||||
"sha256:5c6e3df6bdd396749bafd45314871b3d0af81ff935b2d188385e970052091017",
|
||||
"sha256:608bfdee0d57cf297d32bcbb3c728dc1da0907519d1784962c5f0c68bb93e5a3",
|
||||
"sha256:685ac03cc4ed5ebc15ad5c23bc555d68a87777586d970c2c3e216619a5476223",
|
||||
"sha256:76de421f9c326da8f43d690110f0e79fe3ad1e54be811545d7d91898b4c8493e",
|
||||
"sha256:76edb0a1fa2b4745fb0c99fb9fb98f8b180a1bbceb8be49b087e0b21867e77d3",
|
||||
"sha256:7be600823e4c8631b74e4a0d38384c73f680e6105a7d3c6824fcf226c178c7e6",
|
||||
"sha256:81ff539a12457809666fef6624684c008e00ff6bf455b4b89fd00a140eecd640",
|
||||
"sha256:88af2003543cc40c80f6fca01411892ec52b11021b3dc22ec3bc9d5afd1c5334",
|
||||
"sha256:8c11160913e3dd06c8ffdb5f233a4f254cb449f4dfc0f8f4549eda9e542c93d1",
|
||||
"sha256:8f8182b523b2289f7c415f589118228d30ac8c355baa2f3194ced084dac2dbba",
|
||||
"sha256:9211e7ad69d7c9401cfc0e23d49b69ca65ddd898976d660a2fa5904e3d7a9baa",
|
||||
"sha256:92be919bbc9f7d09f7ae343c38f5bb21c973d2576c1d45600fce4b74bafa7ac0",
|
||||
"sha256:9c82b5b3e043c7af0d95792d0d20ccf68f61a1fec6b3530e718b688422727396",
|
||||
"sha256:9f7c16705f44e0504a3a2a14197c1f0b32a95731d251777dcb060aa83022cb2d",
|
||||
"sha256:9fb218c8a12e51d7ead2a7c9e101a04982237d4855716af2e9499306728fb485",
|
||||
"sha256:a74ba0c356aaa3bb8e3eb79606a87669e7ec6444be352870623025d75a14a2bf",
|
||||
"sha256:b4f69b3700201b80bb82c3a97d5e9254084f6dd5fb5b16fc1a7b974260f89f43",
|
||||
"sha256:bc2ec7c7b5d66b8ec9ce9f720dbb5fa4bace0f545acd34870eff4a369b44bf37",
|
||||
"sha256:c189af0545965fa8d3b9613cfdb0cd37f9d71349e0f7750e1fd704648d475ed2",
|
||||
"sha256:c1fbe7621c167ecaa38ad29643d77a9ce7311583761abf7836e1510c580bf3dd",
|
||||
"sha256:c7cf14a27b0d6adfaebb3ae4153f1e516df54e47e42dcc073d7b3d76111a8d86",
|
||||
"sha256:c9f72a021fbb792ce98306ffb0c348b3c9cb967dce0f12a49aa4c3d3fdefa967",
|
||||
"sha256:cd25d2a9d2b36fcb318882481367956d2cf91329f6892fe5d385c346c0649629",
|
||||
"sha256:ce543ed15570eedbb85df19b0a1a7314a9c8141a36ce089c0a894adbfccb4568",
|
||||
"sha256:ce7b031a6fc11365970e6a5686d7ba8c63e4c1cf1ea143811acbb524295eabed",
|
||||
"sha256:d35e3c8d9b1268cbf5d3670285feb3528f6680420eafe35cccc686b73c1e330f",
|
||||
"sha256:d50b6aec14bc737742ca96e85d6d0a5f9bfbded018264b3b70ff9d8c33485551",
|
||||
"sha256:d5d0dae4cfd56969d23d94dc8e89fb6a217be461c69090768227beb8ed28c0a3",
|
||||
"sha256:d5db32e2a6ccbb3d34d87c87b432959e0db29755727afb37290e10f6e8e62614",
|
||||
"sha256:d72e2ecc68a942e8cf9739619b7f408cc7b272b279b56b2c83c6123fcfa5cdff",
|
||||
"sha256:d737a602fbd82afd892ca746392401b634e278cb65d55c4b7a8f48e9ef8d008d",
|
||||
"sha256:d80cf684b541685fccdd84c485b31ce73fc5c9b5d7523bf1394ce134a60c6883",
|
||||
"sha256:db24668940f82321e746773a4bc617bfac06ec831e5c88b643f91f122a785684",
|
||||
"sha256:dbc02381779d412145331789b40cc7b11fdf449e5d94f6bc0b080db0a56ea3f0",
|
||||
"sha256:dffe31a7f47b603318c609f378ebcd57f1554a3a6a8effbc59c3c69f804296de",
|
||||
"sha256:edf4392b77bdc81f36e92d3a07a5cd072f90253197f4a52a55a8cec48a12483b",
|
||||
"sha256:efe8c0681042536e0d06c11f48cebe759707c9e9abf880ee213541c5b46c5bf3",
|
||||
"sha256:f31f9fdbfecb042d046f9d91270a0ba28368a723302786c0009ee9b9f1f60199",
|
||||
"sha256:f88a0b92277de8e3ca715a0d79d68dc82807457dae3ab8699c758f07c20b3c51",
|
||||
"sha256:faaf07ea35355b01a35cb442dd950d8f1bb5b040a7787791a535de13db15ed90"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==9.5.0"
|
||||
"version": "==10.0.0"
|
||||
},
|
||||
"psycopg2": {
|
||||
"hashes": [
|
||||
"sha256:11aca705ec888e4f4cea97289a0bf0f22a067a32614f6ef64fcf7b8bfbc53744",
|
||||
"sha256:1861a53a6a0fd248e42ea37c957d36950da00266378746588eab4f4b5649e95f",
|
||||
"sha256:2362ee4d07ac85ff0ad93e22c693d0f37ff63e28f0615a16b6635a645f4b9214",
|
||||
"sha256:36c941a767341d11549c0fbdbb2bf5be2eda4caf87f65dfcd7d146828bd27f39",
|
||||
"sha256:53f4ad0a3988f983e9b49a5d9765d663bbe84f508ed655affdb810af9d0972ad",
|
||||
"sha256:869776630c04f335d4124f120b7fb377fe44b0a7645ab3c34b4ba42516951889",
|
||||
"sha256:a8ad4a47f42aa6aec8d061fdae21eaed8d864d4bb0f0cade5ad32ca16fcd6258",
|
||||
"sha256:b81fcb9ecfc584f661b71c889edeae70bae30d3ef74fa0ca388ecda50b1222b7",
|
||||
"sha256:d24ead3716a7d093b90b27b3d73459fe8cd90fd7065cf43b3c40966221d8c394",
|
||||
"sha256:ded2faa2e6dfb430af7713d87ab4abbfc764d8d7fb73eafe96a24155f906ebf5",
|
||||
"sha256:f15158418fd826831b28585e2ab48ed8df2d0d98f502a2b4fe619e7d5ca29011",
|
||||
"sha256:f75001a1cbbe523e00b0ef896a5a1ada2da93ccd752b7636db5a99bc57c44494",
|
||||
"sha256:f7a7a5ee78ba7dc74265ba69e010ae89dae635eea0e97b055fb641a01a31d2b1"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==2.9.6"
|
||||
},
|
||||
"pyasn1": {
|
||||
"hashes": [
|
||||
"sha256:87a2121042a1ac9358cabcaf1d07680ff97ee6404333bacca15f76aa8ad01a57",
|
||||
"sha256:97b7290ca68e62a832558ec3976f15cbf911bf5d7c7039d8b861c2a0ece69fde"
|
||||
],
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'",
|
||||
"version": "==0.5.0"
|
||||
},
|
||||
"pyasn1-modules": {
|
||||
"hashes": [
|
||||
"sha256:5bd01446b736eb9d31512a30d46c1ac3395d676c6f3cafa4c03eb54b9925631c",
|
||||
"sha256:d3ccd6ed470d9ffbc716be08bd90efbd44d0734bc9303818f7336070984a162d"
|
||||
],
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'",
|
||||
"version": "==0.3.0"
|
||||
},
|
||||
"pycparser": {
|
||||
"hashes": [
|
||||
|
@ -373,6 +475,13 @@
|
|||
"markers": "python_version >= '3.7'",
|
||||
"version": "==2.7.0"
|
||||
},
|
||||
"pyopenssl": {
|
||||
"hashes": [
|
||||
"sha256:24f0dc5227396b3e831f4c7f602b950a5e9833d292c8e4a2e06b709292806ae2",
|
||||
"sha256:276f931f55a452e7dea69c7173e984eb2a4407ce413c918aa34b55f82f9b8bac"
|
||||
],
|
||||
"version": "==23.2.0"
|
||||
},
|
||||
"python-dotenv": {
|
||||
"hashes": [
|
||||
"sha256:a8df96034aae6d2d50a4ebe8216326c61c3eb64836776504fcca410e5937a3ba",
|
||||
|
@ -411,6 +520,29 @@
|
|||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
|
||||
"version": "==1.3.1"
|
||||
},
|
||||
"service-identity": {
|
||||
"hashes": [
|
||||
"sha256:87415a691d52fcad954a500cb81f424d0273f8e7e3ee7d766128f4575080f383",
|
||||
"sha256:ecb33cd96307755041e978ab14f8b14e13b40f1fbd525a4dc78f46d2b986431d"
|
||||
],
|
||||
"version": "==23.1.0"
|
||||
},
|
||||
"setuptools": {
|
||||
"hashes": [
|
||||
"sha256:11e52c67415a381d10d6b462ced9cfb97066179f0e871399e006c4ab101fc85f",
|
||||
"sha256:baf1fdb41c6da4cd2eae722e135500da913332ab3f2f5c7d33af9b492acb5235"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==68.0.0"
|
||||
},
|
||||
"six": {
|
||||
"hashes": [
|
||||
"sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926",
|
||||
"sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
|
||||
],
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
|
||||
"version": "==1.16.0"
|
||||
},
|
||||
"social-auth-app-django": {
|
||||
"hashes": [
|
||||
"sha256:0347ca4cd23ea9d15a665da9d22950552fb66b95600e6c2ebae38ca883b3a4ed",
|
||||
|
@ -435,6 +567,55 @@
|
|||
"markers": "python_version >= '3.5'",
|
||||
"version": "==0.4.4"
|
||||
},
|
||||
"twisted": {
|
||||
"extras": [
|
||||
"tls"
|
||||
],
|
||||
"hashes": [
|
||||
"sha256:32acbd40a94f5f46e7b42c109bfae2b302250945561783a8b7a059048f2d4d31",
|
||||
"sha256:86c55f712cc5ab6f6d64e02503352464f0400f66d4f079096d744080afcccbd0"
|
||||
],
|
||||
"markers": "python_full_version >= '3.7.1'",
|
||||
"version": "==22.10.0"
|
||||
},
|
||||
"twisted-iocpsupport": {
|
||||
"hashes": [
|
||||
"sha256:1bdccbb22199fc69fd7744d6d2dfd22d073c028c8611d994b41d2d2ad0e0f40d",
|
||||
"sha256:1dbfac706972bf9ec5ce1ddbc735d2ebba406ad363345df8751ffd5252aa1618",
|
||||
"sha256:1ddfc5fa22ec6f913464b736b3f46e642237f17ac41be47eed6fa9bd52f5d0e0",
|
||||
"sha256:1ea2c3fbdb739c95cc8b3355305cd593d2c9ec56d709207aa1a05d4d98671e85",
|
||||
"sha256:3f39c41c0213a81a9ce0961e30d0d7650f371ad80f8d261007d15a2deb6d5be3",
|
||||
"sha256:4f249d0baac836bb431d6fa0178be063a310136bc489465a831e3abd2d7acafd",
|
||||
"sha256:67bec1716eb8f466ef366bbf262e1467ecc9e20940111207663ac24049785bad",
|
||||
"sha256:6f8c433faaad5d53d30d1da6968d5a3730df415e2efb6864847267a9b51290cd",
|
||||
"sha256:7efcdfafb377f32db90f42bd5fc5bb32cd1e3637ee936cdaf3aff4f4786ab3bf",
|
||||
"sha256:8faceae553cfadc42ad791b1790e7cdecb7751102608c405217f6a26e877e0c5",
|
||||
"sha256:98a6f16ab215f8c1446e9fc60aaed0ab7c746d566aa2f3492a23cea334e6bebb",
|
||||
"sha256:a379ef56a576c8090889f74441bc3822ca31ac82253cc61e8d50631bcb0c26d0",
|
||||
"sha256:aaca8f30c3b7c80d27a33fe9fe0d0bac42b1b012ddc60f677175c30e1becc1f3",
|
||||
"sha256:afb00801fdfbaccf0d0173a722626500023d4a19719ac9f129d1347a32e2fc66",
|
||||
"sha256:db11c80054b52dbdea44d63d5474a44c9a6531882f0e2960268b15123088641a",
|
||||
"sha256:dff43136c33665c2d117a73706aef6f7d6433e5c4560332a118fe066b16b8695"
|
||||
],
|
||||
"markers": "platform_system == 'Windows'",
|
||||
"version": "==1.0.3"
|
||||
},
|
||||
"txaio": {
|
||||
"hashes": [
|
||||
"sha256:aaea42f8aad50e0ecfb976130ada140797e9dcb85fad2cf72b0f37f8cefcb490",
|
||||
"sha256:f9a9216e976e5e3246dfd112ad7ad55ca915606b60b84a757ac769bd404ff704"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==23.1.1"
|
||||
},
|
||||
"typing-extensions": {
|
||||
"hashes": [
|
||||
"sha256:440d5dd3af93b060174bf433bccd69b0babc3b15b1a8dca43789fd7f61514b36",
|
||||
"sha256:b75ddc264f0ba5615db7ba217daeb99701ad295353c45f9e95963337ceeeffb2"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==4.7.1"
|
||||
},
|
||||
"tzdata": {
|
||||
"hashes": [
|
||||
"sha256:11ef1e08e54acb0d4f95bdb1be05da659673de4acbd21bf9c69e94cc5e907a3a",
|
||||
|
@ -458,6 +639,42 @@
|
|||
],
|
||||
"index": "pypi",
|
||||
"version": "==6.5.0"
|
||||
},
|
||||
"zope.interface": {
|
||||
"hashes": [
|
||||
"sha256:042f2381118b093714081fd82c98e3b189b68db38ee7d35b63c327c470ef8373",
|
||||
"sha256:0ec9653825f837fbddc4e4b603d90269b501486c11800d7c761eee7ce46d1bbb",
|
||||
"sha256:12175ca6b4db7621aedd7c30aa7cfa0a2d65ea3a0105393e05482d7a2d367446",
|
||||
"sha256:1592f68ae11e557b9ff2bc96ac8fc30b187e77c45a3c9cd876e3368c53dc5ba8",
|
||||
"sha256:23ac41d52fd15dd8be77e3257bc51bbb82469cf7f5e9a30b75e903e21439d16c",
|
||||
"sha256:424d23b97fa1542d7be882eae0c0fc3d6827784105264a8169a26ce16db260d8",
|
||||
"sha256:4407b1435572e3e1610797c9203ad2753666c62883b921318c5403fb7139dec2",
|
||||
"sha256:48f4d38cf4b462e75fac78b6f11ad47b06b1c568eb59896db5b6ec1094eb467f",
|
||||
"sha256:4c3d7dfd897a588ec27e391edbe3dd320a03684457470415870254e714126b1f",
|
||||
"sha256:5171eb073474a5038321409a630904fd61f12dd1856dd7e9d19cd6fe092cbbc5",
|
||||
"sha256:5a158846d0fca0a908c1afb281ddba88744d403f2550dc34405c3691769cdd85",
|
||||
"sha256:6ee934f023f875ec2cfd2b05a937bd817efcc6c4c3f55c5778cbf78e58362ddc",
|
||||
"sha256:790c1d9d8f9c92819c31ea660cd43c3d5451df1df61e2e814a6f99cebb292788",
|
||||
"sha256:809fe3bf1a91393abc7e92d607976bbb8586512913a79f2bf7d7ec15bd8ea518",
|
||||
"sha256:87b690bbee9876163210fd3f500ee59f5803e4a6607d1b1238833b8885ebd410",
|
||||
"sha256:89086c9d3490a0f265a3c4b794037a84541ff5ffa28bb9c24cc9f66566968464",
|
||||
"sha256:99856d6c98a326abbcc2363827e16bd6044f70f2ef42f453c0bd5440c4ce24e5",
|
||||
"sha256:aab584725afd10c710b8f1e6e208dbee2d0ad009f57d674cb9d1b3964037275d",
|
||||
"sha256:af169ba897692e9cd984a81cb0f02e46dacdc07d6cf9fd5c91e81f8efaf93d52",
|
||||
"sha256:b39b8711578dcfd45fc0140993403b8a81e879ec25d53189f3faa1f006087dca",
|
||||
"sha256:b3f543ae9d3408549a9900720f18c0194ac0fe810cecda2a584fd4dca2eb3bb8",
|
||||
"sha256:d0583b75f2e70ec93f100931660328965bb9ff65ae54695fb3fa0a1255daa6f2",
|
||||
"sha256:dfbbbf0809a3606046a41f8561c3eada9db811be94138f42d9135a5c47e75f6f",
|
||||
"sha256:e538f2d4a6ffb6edfb303ce70ae7e88629ac6e5581870e66c306d9ad7b564a58",
|
||||
"sha256:eba51599370c87088d8882ab74f637de0c4f04a6d08a312dce49368ba9ed5c2a",
|
||||
"sha256:ee4b43f35f5dc15e1fec55ccb53c130adb1d11e8ad8263d68b1284b66a04190d",
|
||||
"sha256:f2363e5fd81afb650085c6686f2ee3706975c54f331b426800b53531191fdf28",
|
||||
"sha256:f299c020c6679cb389814a3b81200fe55d428012c5e76da7e722491f5d205990",
|
||||
"sha256:f72f23bab1848edb7472309e9898603141644faec9fd57a823ea6b4d1c4c8995",
|
||||
"sha256:fa90bac61c9dc3e1a563e5babb3fd2c0c1c80567e815442ddbe561eadc803b30"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==6.0"
|
||||
}
|
||||
},
|
||||
"develop": {}
|
||||
|
|
BIN
packages/GDAL-3.4.3-cp311-cp311-win_amd64.whl
Normal file
BIN
packages/GDAL-3.4.3-cp311-cp311-win_amd64.whl
Normal file
Binary file not shown.
5
packages/readme.md
Normal file
5
packages/readme.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
Some stuff we need to manually install
|
||||
|
||||
> pipenv install
|
||||
|
||||
Running the command above should automatically install these packages
|
|
@ -5,6 +5,7 @@ from .models import CustomUser
|
|||
from year_levels.models import Year_Level
|
||||
from semesters.models import Semester
|
||||
from courses.models import Course
|
||||
from subjects.models import Subject
|
||||
|
||||
|
||||
class CustomUserForm(forms.ModelForm):
|
||||
|
@ -14,6 +15,8 @@ class CustomUserForm(forms.ModelForm):
|
|||
queryset=Semester.objects.all(), required=False)
|
||||
course = forms.ModelChoiceField(
|
||||
queryset=Course.objects.all(), required=False)
|
||||
subjects = forms.ModelMultipleChoiceField(
|
||||
queryset=Subject.objects.all(), required=False, widget=forms.CheckboxSelectMultiple)
|
||||
avatar = forms.ImageField(required=False)
|
||||
|
||||
class Meta:
|
||||
|
@ -27,7 +30,7 @@ class CustomUserAdmin(UserAdmin):
|
|||
|
||||
fieldsets = UserAdmin.fieldsets + (
|
||||
(None, {'fields': ('student_id_number',
|
||||
'year_level', 'semester', 'course', 'avatar', 'is_student', 'is_banned')}),
|
||||
'year_level', 'semester', 'course', 'subjects', 'avatar', 'is_student', 'is_banned')}),
|
||||
)
|
||||
|
||||
|
||||
|
|
0
stude/accounts/management/__init__.py
Normal file
0
stude/accounts/management/__init__.py
Normal file
0
stude/accounts/management/commands/__init__.py
Normal file
0
stude/accounts/management/commands/__init__.py
Normal file
14
stude/accounts/management/commands/custom_migrate.py
Normal file
14
stude/accounts/management/commands/custom_migrate.py
Normal file
|
@ -0,0 +1,14 @@
|
|||
from django.core.management.base import BaseCommand
|
||||
from django.db import connection
|
||||
from django.core.management import call_command
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = 'Run InitSpatialMetaData and then migrate'
|
||||
|
||||
def handle(self, *args, **kwargs):
|
||||
with connection.cursor() as cursor:
|
||||
cursor.execute('SELECT InitSpatialMetaData(1);')
|
||||
|
||||
# Call the Django migrate command
|
||||
call_command('migrate')
|
|
@ -1,4 +1,4 @@
|
|||
# Generated by Django 4.2.2 on 2023-06-27 15:21
|
||||
# Generated by Django 4.2.3 on 2023-07-18 07:43
|
||||
|
||||
import accounts.models
|
||||
import django.contrib.auth.models
|
||||
|
@ -25,10 +25,10 @@ class Migration(migrations.Migration):
|
|||
('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')),
|
||||
('email', models.EmailField(blank=True, max_length=254, verbose_name='email address')),
|
||||
('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')),
|
||||
('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')),
|
||||
('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')),
|
||||
('first_name', models.CharField(max_length=100)),
|
||||
('last_name', models.CharField(max_length=100)),
|
||||
('is_active', models.BooleanField(default=False)),
|
||||
('is_student', models.BooleanField(default=True)),
|
||||
('is_studying', models.BooleanField(default=False)),
|
||||
('is_banned', models.BooleanField(default=False)),
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Generated by Django 4.2.2 on 2023-06-27 15:21
|
||||
# Generated by Django 4.2.3 on 2023-07-18 07:43
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
@ -12,15 +12,16 @@ class Migration(migrations.Migration):
|
|||
('auth', '0012_alter_user_first_name_max_length'),
|
||||
('year_levels', '0001_initial'),
|
||||
('accounts', '0001_initial'),
|
||||
('courses', '0002_initial'),
|
||||
('semesters', '0001_initial'),
|
||||
('courses', '0002_initial'),
|
||||
('subjects', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='customuser',
|
||||
name='course',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='courses.course'),
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='courses.course'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='customuser',
|
||||
|
@ -30,7 +31,12 @@ class Migration(migrations.Migration):
|
|||
migrations.AddField(
|
||||
model_name='customuser',
|
||||
name='semester',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='semesters.semester'),
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='semesters.semester'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='customuser',
|
||||
name='subjects',
|
||||
field=models.ManyToManyField(to='subjects.subject'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='customuser',
|
||||
|
@ -40,6 +46,6 @@ class Migration(migrations.Migration):
|
|||
migrations.AddField(
|
||||
model_name='customuser',
|
||||
name='year_level',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='year_levels.year_level'),
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='year_levels.year_level'),
|
||||
),
|
||||
]
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
# Generated by Django 4.2.2 on 2023-06-28 03:09
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('subjects', '0002_subjectstudent_subject_students'),
|
||||
('accounts', '0002_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='customuser',
|
||||
name='subjects',
|
||||
field=models.ManyToManyField(related_name='SubjectStudent_user', through='subjects.SubjectStudent', to='subjects.subject'),
|
||||
),
|
||||
]
|
|
@ -1,32 +0,0 @@
|
|||
# Generated by Django 4.2.2 on 2023-07-04 10:04
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('semesters', '0001_initial'),
|
||||
('courses', '0002_initial'),
|
||||
('year_levels', '0001_initial'),
|
||||
('accounts', '0003_customuser_subjects'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='customuser',
|
||||
name='course',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='courses.course'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='customuser',
|
||||
name='semester',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='semesters.semester'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='customuser',
|
||||
name='year_level',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='year_levels.year_level'),
|
||||
),
|
||||
]
|
|
@ -1,18 +0,0 @@
|
|||
# Generated by Django 4.2.2 on 2023-07-04 11:33
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('accounts', '0004_alter_customuser_course_alter_customuser_semester_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='customuser',
|
||||
name='is_active',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
]
|
|
@ -20,11 +20,9 @@ def validate_student_id(value):
|
|||
class CustomUser(AbstractUser):
|
||||
def _get_upload_to(instance, filename):
|
||||
base_filename, file_extension = os.path.splitext(filename)
|
||||
# Convert filename to a slug format
|
||||
cleaned_filename = slugify(base_filename)
|
||||
# Get the student ID number
|
||||
student_id = str(instance.student_id_number)
|
||||
new_filename = f"{student_id}_{cleaned_filename}{file_extension}"
|
||||
new_filename = f"{student_id}_{file_extension}"
|
||||
return os.path.join('avatars', new_filename)
|
||||
|
||||
first_name = models.CharField(max_length=100)
|
||||
|
@ -55,8 +53,7 @@ class CustomUser(AbstractUser):
|
|||
on_delete=models.SET_NULL,
|
||||
null=True
|
||||
)
|
||||
subjects = models.ManyToManyField(
|
||||
'subjects.Subject', through='subjects.SubjectStudent', related_name='SubjectStudent_user')
|
||||
subjects = models.ManyToManyField('subjects.Subject')
|
||||
|
||||
@property
|
||||
def full_name(self):
|
||||
|
@ -80,3 +77,23 @@ def create_superuser(sender, **kwargs):
|
|||
# Activate the superuser
|
||||
superuser.is_active = True
|
||||
superuser.save()
|
||||
|
||||
User = CustomUser
|
||||
username = 'keannu125'
|
||||
email = os.getenv('DJANGO_ADMIN_EMAIL')
|
||||
password = os.getenv('DJANGO_ADMIN_PASSWORD')
|
||||
student_id_number = '2020300490'
|
||||
first_name = 'Keannu'
|
||||
last_name = 'Bernasol'
|
||||
# course = 'Bachelor of Science in Information Technology'
|
||||
# year_level = '1st Year'
|
||||
# semester = '1st Semester'
|
||||
|
||||
if not User.objects.filter(username=username).exists():
|
||||
# Create the superuser with is_active set to False
|
||||
user = User.objects.create_user(
|
||||
username=username, email=email, password=password, first_name=first_name, last_name=last_name, student_id_number=student_id_number)
|
||||
|
||||
# Activate the superuser
|
||||
user.is_active = True
|
||||
user.save()
|
||||
|
|
|
@ -11,23 +11,69 @@ from django.contrib.auth.password_validation import validate_password
|
|||
from courses.models import Course
|
||||
from year_levels.models import Year_Level
|
||||
from semesters.models import Semester
|
||||
from subjects.models import Subject
|
||||
from django.contrib.gis.geos import Point
|
||||
|
||||
|
||||
class CustomUserSerializer(BaseUserSerializer):
|
||||
user_status = StudentStatusSerializer(
|
||||
source='studentstatus', read_only=True)
|
||||
# user_status = StudentStatusSerializer(
|
||||
# source='studentstatus', read_only=True)
|
||||
course_shortname = serializers.SerializerMethodField()
|
||||
yearlevel_shortname = serializers.SerializerMethodField()
|
||||
semester_shortname = serializers.SerializerMethodField()
|
||||
course = serializers.SlugRelatedField(
|
||||
many=False, slug_field='name', queryset=Course.objects.all(), required=False, allow_null=True)
|
||||
year_level = serializers.SlugRelatedField(
|
||||
many=False, slug_field='name', queryset=Year_Level.objects.all(), required=False, allow_null=True)
|
||||
semester = serializers.SlugRelatedField(
|
||||
many=False, slug_field='name', queryset=Semester.objects.all(), required=False, allow_null=True)
|
||||
subjects = serializers.SlugRelatedField(
|
||||
many=True, slug_field='name', queryset=Subject.objects.all(), required=False, allow_null=True)
|
||||
|
||||
class Meta(BaseUserSerializer.Meta):
|
||||
model = CustomUser
|
||||
fields = ('username', 'email',
|
||||
'student_id_number', 'year_level', 'semester', 'course', 'subjects', 'avatar', 'first_name', 'last_name', 'is_banned', 'user_status')
|
||||
read_only_fields = ('is_banned', 'user_status')
|
||||
'student_id_number', 'year_level', 'yearlevel_shortname', 'semester', 'semester_shortname', 'course', 'course_shortname', 'subjects', 'avatar', 'first_name', 'last_name', 'is_banned')
|
||||
read_only_fields = ('is_banned', 'user_status', 'yearlevel_shortname',
|
||||
'semester_shortname', 'course_shortname')
|
||||
|
||||
def get_course_shortname(self, instance):
|
||||
return instance.course.shortname if instance.course else None
|
||||
|
||||
def get_yearlevel_shortname(self, instance):
|
||||
return instance.year_level.shortname if instance.year_level else None
|
||||
|
||||
def get_semester_shortname(self, instance):
|
||||
return instance.semester.shortname if instance.semester else None
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
# First, we'll remove all the existing subjects from the user
|
||||
print(validated_data)
|
||||
# If course, year_level, or semester is changed
|
||||
if any(field in validated_data for field in ['course', 'year_level', 'semester']):
|
||||
if (instance.course != validated_data['course'] or
|
||||
instance.year_level != validated_data['year_level'] or
|
||||
instance.semester != validated_data['semester']):
|
||||
|
||||
# Clear all subjects
|
||||
instance.subjects.clear()
|
||||
# Update the user instance with the validated data
|
||||
instance = super().update(instance, validated_data)
|
||||
# Then add new subjects matching the new criteria
|
||||
self.add_subjects(instance)
|
||||
|
||||
# Else update as usual
|
||||
else:
|
||||
instance = super().update(instance, validated_data)
|
||||
|
||||
return instance
|
||||
|
||||
def add_subjects(self, instance):
|
||||
# Get the matching subjects based on the user's course, year level, and semester
|
||||
matching_subjects = Subject.objects.filter(
|
||||
courses=instance.course, year_levels=instance.year_level, semesters=instance.semester)
|
||||
# Add the matching subjects to the user's subjects list
|
||||
instance.subjects.add(*matching_subjects)
|
||||
|
||||
# The model from your custom user
|
||||
|
||||
|
@ -35,7 +81,10 @@ class CustomUserSerializer(BaseUserSerializer):
|
|||
class UserRegistrationSerializer(serializers.ModelSerializer):
|
||||
email = serializers.EmailField(required=True)
|
||||
student_id_number = serializers.CharField(required=True)
|
||||
password = serializers.CharField(write_only=True)
|
||||
password = serializers.CharField(
|
||||
write_only=True, style={'input_type': 'password', 'placeholder': 'Password'})
|
||||
subjects = serializers.SlugRelatedField(
|
||||
many=True, slug_field='name', queryset=Subject.objects.all(), required=False, allow_null=True)
|
||||
|
||||
class Meta:
|
||||
model = CustomUser # Use your custom user model here
|
||||
|
@ -64,8 +113,7 @@ class UserRegistrationSerializer(serializers.ModelSerializer):
|
|||
StudentStatus.objects.create(
|
||||
user=user,
|
||||
active=False,
|
||||
x=None,
|
||||
y=None,
|
||||
location=Point(0, 0),
|
||||
subject=None
|
||||
)
|
||||
return user
|
||||
|
|
|
@ -9,5 +9,6 @@ urlpatterns = [
|
|||
path('semesters/', include('semesters.urls')),
|
||||
path('subjects/', include('subjects.urls')),
|
||||
path('study_groups/', include('study_groups.urls')),
|
||||
path('messages/', include('studygroup_messages.urls'))
|
||||
path('messages/', include('studygroup_messages.urls')),
|
||||
path('landmarks/', include('landmarks.urls')),
|
||||
]
|
||||
|
|
|
@ -14,6 +14,7 @@ from pathlib import Path
|
|||
from dotenv import load_dotenv # Python dotenv
|
||||
import os
|
||||
|
||||
|
||||
load_dotenv() # loads the configs from .env
|
||||
|
||||
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
||||
|
@ -50,8 +51,21 @@ else:
|
|||
EMAIL_PORT = str(os.getenv('PROD_EMAIL_PORT'))
|
||||
EMAIL_USE_TLS = str(os.getenv('PROD_EMAIL_TLS'))
|
||||
|
||||
# Will need to install OSGeo4W for this!
|
||||
if os.name == 'nt':
|
||||
OSGEO4W = r"C:\OSGeo4W"
|
||||
if not os.path.isdir(OSGEO4W):
|
||||
OSGEO4W += '64'
|
||||
os.environ['OSGEO4W_ROOT'] = OSGEO4W
|
||||
os.environ['GDAL_DATA'] = "C:\Program Files\GDAL\gdal-data"
|
||||
os.environ['PROJ_LIB'] = OSGEO4W + r"\share\proj"
|
||||
GDAL_LIBRARY_PATH = r'C:\OSGeo4W64\bin\gdal204'
|
||||
os.environ['PATH'] = OSGEO4W + r"\bin;" + os.environ['PATH']
|
||||
|
||||
# Application definition
|
||||
GEOS_LIBRARY_PATH = str(os.environ.get('VIRTUAL_ENV') +
|
||||
r"\Lib\site-packages\osgeo\geos_c.dll")
|
||||
GDAL_LIBRARY_PATH = str(os.environ.get('VIRTUAL_ENV') +
|
||||
r"\Lib\site-packages\osgeo\gdal304.dll")
|
||||
|
||||
INSTALLED_APPS = [
|
||||
'daphne',
|
||||
|
@ -61,6 +75,7 @@ INSTALLED_APPS = [
|
|||
'django.contrib.sessions',
|
||||
'django.contrib.messages',
|
||||
'django.contrib.staticfiles',
|
||||
'django.contrib.gis',
|
||||
'rest_framework',
|
||||
'rest_framework_simplejwt',
|
||||
'djoser',
|
||||
|
@ -72,6 +87,8 @@ INSTALLED_APPS = [
|
|||
'subjects',
|
||||
'study_groups',
|
||||
'studygroup_messages',
|
||||
'leaflet',
|
||||
'landmarks',
|
||||
]
|
||||
|
||||
MIDDLEWARE = [
|
||||
|
@ -123,11 +140,18 @@ WSGI_APPLICATION = 'config.wsgi.application'
|
|||
# Database
|
||||
# https://docs.djangoproject.com/en/4.2/ref/settings/#databases
|
||||
|
||||
DATABASES = {
|
||||
"""DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.sqlite3',
|
||||
'NAME': BASE_DIR / 'db.sqlite3',
|
||||
}
|
||||
}"""
|
||||
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.contrib.gis.db.backends.spatialite',
|
||||
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
|
||||
}
|
||||
}
|
||||
|
||||
AUTH_USER_MODEL = 'accounts.CustomUser'
|
||||
|
@ -203,3 +227,11 @@ SITE_NAME = 'Stud-E'
|
|||
JWT_TOKEN_LIFETIME = 10800
|
||||
ACCESS_TOKEN_LIFETIME = JWT_TOKEN_LIFETIME
|
||||
REFRESH_TOKEN_LIFETIME = 24 * JWT_TOKEN_LIFETIME
|
||||
|
||||
LEAFLET_CONFIG = {
|
||||
'DEFAULT_CENTER': (8.48567, 124.65642),
|
||||
'DEFAULT_ZOOM': 19,
|
||||
'MAX_ZOOM': 20,
|
||||
'MIN_ZOOM': 3,
|
||||
'SCALE': 'both'
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
from django.contrib import admin
|
||||
from .models import Course, SubjectCourse
|
||||
from .models import Course
|
||||
|
||||
|
||||
admin.site.register(Course)
|
||||
admin.site.register(SubjectCourse)
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
# Generated by Django 4.2.2 on 2023-06-27 15:21
|
||||
# Generated by Django 4.2.3 on 2023-07-18 07:43
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
@ -20,11 +19,4 @@ class Migration(migrations.Migration):
|
|||
('shortname', models.CharField(max_length=16)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='SubjectCourse',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('course', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='courses.course')),
|
||||
],
|
||||
),
|
||||
]
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
# Generated by Django 4.2.2 on 2023-06-27 15:21
|
||||
# Generated by Django 4.2.3 on 2023-07-18 07:43
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
@ -9,19 +8,14 @@ class Migration(migrations.Migration):
|
|||
initial = True
|
||||
|
||||
dependencies = [
|
||||
('subjects', '0001_initial'),
|
||||
('courses', '0001_initial'),
|
||||
('subjects', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='subjectcourse',
|
||||
name='subject',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='subjects.subject'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='course',
|
||||
name='subjects',
|
||||
field=models.ManyToManyField(related_name='SubjectCourse_course', through='courses.SubjectCourse', to='subjects.subject'),
|
||||
field=models.ManyToManyField(related_name='SubjectCourse_course', through='subjects.SubjectCourse', to='subjects.subject'),
|
||||
),
|
||||
]
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
# Generated by Django 4.2.3 on 2023-07-18 10:28
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('courses', '0002_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='course',
|
||||
name='name',
|
||||
field=models.CharField(max_length=64, unique=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='course',
|
||||
name='shortname',
|
||||
field=models.CharField(max_length=16, unique=True),
|
||||
),
|
||||
]
|
|
@ -5,21 +5,15 @@ from django.db import models
|
|||
|
||||
|
||||
class Course(models.Model):
|
||||
name = models.CharField(max_length=64)
|
||||
shortname = models.CharField(max_length=16)
|
||||
name = models.CharField(max_length=64, unique=True)
|
||||
shortname = models.CharField(max_length=16, unique=True)
|
||||
subjects = models.ManyToManyField(
|
||||
'subjects.Subject', related_name='SubjectCourse_course', through='courses.SubjectCourse')
|
||||
'subjects.Subject', related_name='SubjectCourse_course', through='subjects.SubjectCourse')
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class SubjectCourse(models.Model):
|
||||
subject = models.ForeignKey('subjects.Subject', on_delete=models.CASCADE)
|
||||
course = models.ForeignKey(
|
||||
'courses.Course', on_delete=models.CASCADE, null=True)
|
||||
|
||||
|
||||
@receiver(post_migrate)
|
||||
def populate_courses(sender, **kwargs):
|
||||
if sender.name == 'courses':
|
||||
|
|
0
stude/landmarks/__init__.py
Normal file
0
stude/landmarks/__init__.py
Normal file
5
stude/landmarks/admin.py
Normal file
5
stude/landmarks/admin.py
Normal file
|
@ -0,0 +1,5 @@
|
|||
from django.contrib import admin
|
||||
from leaflet.admin import LeafletGeoAdmin
|
||||
from .models import Landmark
|
||||
|
||||
admin.site.register(Landmark, LeafletGeoAdmin)
|
6
stude/landmarks/apps.py
Normal file
6
stude/landmarks/apps.py
Normal file
|
@ -0,0 +1,6 @@
|
|||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class LandmarksConfig(AppConfig):
|
||||
default_auto_field = 'django.db.models.BigAutoField'
|
||||
name = 'landmarks'
|
23
stude/landmarks/migrations/0001_initial.py
Normal file
23
stude/landmarks/migrations/0001_initial.py
Normal file
|
@ -0,0 +1,23 @@
|
|||
# Generated by Django 4.2.3 on 2023-07-18 07:43
|
||||
|
||||
import django.contrib.gis.db.models.fields
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Landmark',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=64)),
|
||||
('location', django.contrib.gis.db.models.fields.PolygonField(srid=4326)),
|
||||
],
|
||||
),
|
||||
]
|
0
stude/landmarks/migrations/__init__.py
Normal file
0
stude/landmarks/migrations/__init__.py
Normal file
218
stude/landmarks/models.py
Normal file
218
stude/landmarks/models.py
Normal file
|
@ -0,0 +1,218 @@
|
|||
from django.db import models
|
||||
from django.contrib.gis.db import models as gis_models
|
||||
from django.contrib.gis.geos import GEOSGeometry
|
||||
from django.db.models.signals import post_migrate
|
||||
from django.dispatch import receiver
|
||||
# Create your models here.
|
||||
|
||||
|
||||
class Landmark(models.Model):
|
||||
name = models.CharField(max_length=64)
|
||||
location = gis_models.PolygonField(srid=4326)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
@receiver(post_migrate)
|
||||
def populate_landmarks(sender, **kwargs):
|
||||
if sender.name == 'landmarks':
|
||||
SRID = 4326
|
||||
Landmark.objects.get_or_create(
|
||||
name='Gymnasium',
|
||||
location=GEOSGeometry(
|
||||
'POLYGON ((124.656383 8.485963, 124.656576 8.485483, 124.657009 8.485659, 124.656827 8.486126, 124.656383 8.485963))',
|
||||
srid=SRID
|
||||
)
|
||||
)
|
||||
Landmark.objects.get_or_create(
|
||||
name='Arts & Culture Building',
|
||||
location=GEOSGeometry(
|
||||
'POLYGON ((124.658427 8.486268, 124.658432 8.48617, 124.658582 8.486202, 124.658555 8.4863, 124.658427 8.486268))',
|
||||
srid=SRID
|
||||
)
|
||||
)
|
||||
Landmark.objects.get_or_create(
|
||||
name='Guidance and Testing Center',
|
||||
location=GEOSGeometry(
|
||||
'POLYGON ((124.658191 8.486326, 124.658377 8.486359, 124.658394 8.486261, 124.658209 8.486231, 124.658191 8.486326))',
|
||||
srid=SRID
|
||||
)
|
||||
)
|
||||
Landmark.objects.get_or_create(
|
||||
name='Old Civil Engineering Building',
|
||||
location=GEOSGeometry(
|
||||
'POLYGON ((124.657244 8.485617, 124.657228 8.485743, 124.658014 8.485844, 124.658032 8.485711, 124.657244 8.485617))',
|
||||
srid=SRID
|
||||
)
|
||||
)
|
||||
Landmark.objects.get_or_create(
|
||||
name='ITB Building',
|
||||
location=GEOSGeometry(
|
||||
'POLYGON ((124.658035 8.48622, 124.658056 8.485906, 124.658592 8.485942, 124.658582 8.486077, 124.6582 8.486056, 124.658188 8.486231, 124.658035 8.48622))',
|
||||
srid=SRID
|
||||
)
|
||||
)
|
||||
Landmark.objects.get_or_create(
|
||||
name='SPED Center',
|
||||
location=GEOSGeometry(
|
||||
'POLYGON ((124.658236 8.485918, 124.658348 8.485923, 124.658348 8.485874, 124.658236 8.485881, 124.658236 8.485918))',
|
||||
srid=SRID
|
||||
)
|
||||
)
|
||||
Landmark.objects.get_or_create(
|
||||
name='Administration Building',
|
||||
location=GEOSGeometry(
|
||||
'POLYGON ((124.657236 8.486097, 124.657213 8.486064, 124.657196 8.486074, 124.657177 8.486037, 124.657279 8.485944, 124.657401 8.485893, 124.657426 8.485935, 124.657411 8.485946, 124.65743 8.485971, 124.657236 8.486097))',
|
||||
srid=SRID
|
||||
)
|
||||
)
|
||||
Landmark.objects.get_or_create(
|
||||
name='Informations and Communications Technology Building',
|
||||
location=GEOSGeometry(
|
||||
'POLYGON ((124.657204 8.486478, 124.657142 8.486326, 124.657201 8.486307, 124.657273 8.486272, 124.657291 8.486287, 124.65741 8.486216, 124.65752 8.486097, 124.657552 8.486031, 124.657537 8.486025, 124.657523 8.486009, 124.657513 8.485994, 124.657512 8.485978, 124.657515 8.48596, 124.657521 8.485944, 124.657535 8.485927, 124.65756 8.485914, 124.657578 8.48591, 124.657592 8.485913, 124.65761 8.485921, 124.657627 8.485934, 124.657639 8.485948, 124.657639 8.485963, 124.657639 8.485978, 124.657638 8.485992, 124.657626 8.486008, 124.657605 8.486025, 124.657666 8.486053, 124.657634 8.486139, 124.65758 8.486206, 124.657511 8.486279, 124.657425 8.486352, 124.65735 8.486405, 124.657204 8.486478))',
|
||||
srid=SRID
|
||||
)
|
||||
)
|
||||
Landmark.objects.get_or_create(
|
||||
name='Finance and Accounting Building',
|
||||
location=GEOSGeometry(
|
||||
'POLYGON ((124.656457 8.486273, 124.656844 8.486425, 124.656974 8.486104, 124.656855 8.486057, 124.656772 8.486259, 124.656503 8.486157, 124.656457 8.486273))',
|
||||
srid=SRID
|
||||
)
|
||||
)
|
||||
Landmark.objects.get_or_create(
|
||||
name='Culinary Building',
|
||||
location=GEOSGeometry(
|
||||
'POLYGON ((124.65708 8.485527, 124.657104 8.485261, 124.657205 8.485268, 124.657175 8.485533, 124.65708 8.485527))',
|
||||
srid=SRID
|
||||
)
|
||||
)
|
||||
Landmark.objects.get_or_create(
|
||||
name='Science Centrum Building',
|
||||
location=GEOSGeometry(
|
||||
'POLYGON ((124.657114 8.485195, 124.657128 8.484964, 124.657224 8.48497, 124.657212 8.485202, 124.657114 8.485195))',
|
||||
srid=SRID
|
||||
)
|
||||
)
|
||||
Landmark.objects.get_or_create(
|
||||
name='Engineering Complex Right Wing',
|
||||
location=GEOSGeometry(
|
||||
'POLYGON ((124.656961 8.484943, 124.656934 8.48482, 124.656959 8.484813, 124.656939 8.484744, 124.657229 8.484684, 124.657228 8.484898, 124.656961 8.484943))',
|
||||
srid=SRID
|
||||
)
|
||||
)
|
||||
Landmark.objects.get_or_create(
|
||||
name='Engineering Complex Left Wing',
|
||||
location=GEOSGeometry(
|
||||
'POLYGON ((124.656949 8.484975, 124.656962 8.484944, 124.656935 8.484821, 124.656701 8.484767, 124.65666 8.484765, 124.656632 8.484772, 124.656605 8.484783, 124.656596 8.484798, 124.656591 8.484813, 124.656588 8.484828, 124.656587 8.484858, 124.656595 8.484878, 124.656604 8.484893, 124.65662 8.484907, 124.656647 8.484922, 124.656681 8.484935, 124.656693 8.484903, 124.656949 8.484975))',
|
||||
srid=SRID
|
||||
)
|
||||
)
|
||||
Landmark.objects.get_or_create(
|
||||
name='Cafeteria',
|
||||
location=GEOSGeometry(
|
||||
'POLYGON ((124.656651 8.48535, 124.656772 8.485021, 124.656917 8.485077, 124.656799 8.485403, 124.656651 8.48535))',
|
||||
srid=SRID
|
||||
)
|
||||
)
|
||||
Landmark.objects.get_or_create(
|
||||
name='HRM Building',
|
||||
location=GEOSGeometry(
|
||||
'POLYGON ((124.656359 8.486151, 124.656471 8.486198, 124.656497 8.486141, 124.656627 8.486189, 124.656655 8.486118, 124.65641 8.486023, 124.656359 8.486151))',
|
||||
srid=SRID
|
||||
)
|
||||
)
|
||||
Landmark.objects.get_or_create(
|
||||
name='Sports Complex',
|
||||
location=GEOSGeometry(
|
||||
'POLYGON ((124.65625 8.486543, 124.656813 8.486763, 124.65687 8.486617, 124.656306 8.486401, 124.65625 8.486543))',
|
||||
srid=SRID
|
||||
)
|
||||
)
|
||||
Landmark.objects.get_or_create(
|
||||
name='Printing Press',
|
||||
location=GEOSGeometry(
|
||||
'POLYGON ((124.656053 8.486711, 124.656092 8.486597, 124.656195 8.486636, 124.656152 8.486748, 124.656053 8.486711))',
|
||||
srid=SRID
|
||||
)
|
||||
)
|
||||
Landmark.objects.get_or_create(
|
||||
name='Learning Resource Center',
|
||||
location=GEOSGeometry(
|
||||
'POLYGON ((124.655575 8.486698, 124.655663 8.486454, 124.655783 8.486502, 124.655799 8.486458, 124.655916 8.486499, 124.655899 8.486543, 124.656041 8.486593, 124.655951 8.486833, 124.655575 8.486698))',
|
||||
srid=SRID
|
||||
)
|
||||
)
|
||||
Landmark.objects.get_or_create(
|
||||
name='Food Innovation Center',
|
||||
location=GEOSGeometry(
|
||||
'POLYGON ((124.655633 8.486304, 124.655681 8.486175, 124.656239 8.486394, 124.65619 8.486516, 124.656101 8.486482, 124.656085 8.486523, 124.656007 8.486494, 124.656022 8.486454, 124.655633 8.486304))',
|
||||
srid=SRID
|
||||
)
|
||||
)
|
||||
Landmark.objects.get_or_create(
|
||||
name='Technology Building',
|
||||
location=GEOSGeometry(
|
||||
'POLYGON ((124.655184 8.486766, 124.655252 8.486674, 124.655632 8.486823, 124.655575 8.486919, 124.655184 8.486766))',
|
||||
srid=SRID
|
||||
)
|
||||
)
|
||||
Landmark.objects.get_or_create(
|
||||
name='Foods Trade Building',
|
||||
location=GEOSGeometry(
|
||||
'POLYGON ((124.655251 8.486585, 124.655427 8.486651, 124.655478 8.486521, 124.655416 8.4865, 124.65552 8.486246, 124.655571 8.486263, 124.65563 8.486128, 124.655451 8.486059, 124.655251 8.486585))',
|
||||
srid=SRID
|
||||
)
|
||||
)
|
||||
Landmark.objects.get_or_create(
|
||||
name='Old Medical Building',
|
||||
location=GEOSGeometry(
|
||||
'POLYGON ((124.655574 8.485952, 124.655708 8.486004, 124.655732 8.485944, 124.655594 8.485895, 124.655574 8.485952))',
|
||||
srid=SRID
|
||||
)
|
||||
)
|
||||
Landmark.objects.get_or_create(
|
||||
name='Old Science Building',
|
||||
location=GEOSGeometry(
|
||||
'POLYGON ((124.655534 8.485857, 124.655629 8.485588, 124.655795 8.485647, 124.655755 8.485757, 124.656271 8.485946, 124.656212 8.486104, 124.655534 8.485857))',
|
||||
srid=SRID
|
||||
)
|
||||
)
|
||||
Landmark.objects.get_or_create(
|
||||
name='Science Complex',
|
||||
location=GEOSGeometry(
|
||||
'POLYGON ((124.655743 8.485616, 124.655743 8.48563, 124.655829 8.485659, 124.655845 8.485623, 124.656325 8.485793, 124.656381 8.485629, 124.655806 8.485427, 124.655761 8.485558, 124.655742 8.485547, 124.655719 8.485608, 124.655743 8.485616))',
|
||||
srid=SRID
|
||||
)
|
||||
)
|
||||
Landmark.objects.get_or_create(
|
||||
name='SUMP PIT',
|
||||
location=GEOSGeometry(
|
||||
'POLYGON ((124.65478 8.486829, 124.654976 8.486897, 124.65502 8.486779, 124.654826 8.486707, 124.65478 8.486829))',
|
||||
srid=SRID
|
||||
)
|
||||
)
|
||||
Landmark.objects.get_or_create(
|
||||
name='Fabrication Laboratory',
|
||||
location=GEOSGeometry(
|
||||
'POLYGON ((124.654816 8.486586, 124.654933 8.4863, 124.65511 8.486373, 124.654993 8.486658, 124.654816 8.486586))',
|
||||
srid=SRID
|
||||
)
|
||||
)
|
||||
Landmark.objects.get_or_create(
|
||||
name='Old Student Center',
|
||||
location=GEOSGeometry(
|
||||
'POLYGON ((124.655046 8.486251, 124.655178 8.485921, 124.655311 8.485972, 124.655173 8.486301, 124.655046 8.486251))',
|
||||
srid=SRID
|
||||
)
|
||||
)
|
||||
Landmark.objects.get_or_create(
|
||||
name='Old Education Building',
|
||||
location=GEOSGeometry(
|
||||
'POLYGON ((124.655181 8.485909, 124.655307 8.485612, 124.655432 8.485663, 124.655305 8.485959, 124.655181 8.485909))',
|
||||
srid=SRID
|
||||
)
|
||||
)
|
||||
|
||||
# Add more predefined records as needed
|
8
stude/landmarks/serializers.py
Normal file
8
stude/landmarks/serializers.py
Normal file
|
@ -0,0 +1,8 @@
|
|||
from .models import Landmark
|
||||
from rest_framework import serializers
|
||||
|
||||
|
||||
class LandmarkSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = Landmark
|
||||
fields = '__all__'
|
3
stude/landmarks/tests.py
Normal file
3
stude/landmarks/tests.py
Normal file
|
@ -0,0 +1,3 @@
|
|||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
6
stude/landmarks/urls.py
Normal file
6
stude/landmarks/urls.py
Normal file
|
@ -0,0 +1,6 @@
|
|||
from django.urls import path
|
||||
from .views import LandmarkListView
|
||||
|
||||
urlpatterns = [
|
||||
path('', LandmarkListView.as_view()),
|
||||
]
|
10
stude/landmarks/views.py
Normal file
10
stude/landmarks/views.py
Normal file
|
@ -0,0 +1,10 @@
|
|||
from rest_framework import generics
|
||||
from rest_framework.permissions import IsAuthenticated
|
||||
from .serializers import LandmarkSerializer
|
||||
from .models import Landmark
|
||||
|
||||
|
||||
class LandmarkListView(generics.ListAPIView):
|
||||
serializer_class = LandmarkSerializer
|
||||
# permission_classes = [IsAuthenticated]
|
||||
queryset = Landmark.objects.all()
|
|
@ -1,4 +1,4 @@
|
|||
# Generated by Django 4.2.2 on 2023-06-27 15:21
|
||||
# Generated by Django 4.2.3 on 2023-07-18 07:43
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
# Generated by Django 4.2.3 on 2023-07-18 10:28
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('semesters', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='semester',
|
||||
name='name',
|
||||
field=models.CharField(max_length=64, unique=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='semester',
|
||||
name='shortname',
|
||||
field=models.CharField(max_length=16, unique=True),
|
||||
),
|
||||
]
|
|
@ -6,8 +6,8 @@ from django.dispatch import receiver
|
|||
|
||||
|
||||
class Semester(models.Model):
|
||||
name = models.CharField(max_length=64)
|
||||
shortname = models.CharField(max_length=16)
|
||||
name = models.CharField(max_length=64, unique=True)
|
||||
shortname = models.CharField(max_length=16, unique=True)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
|
|
@ -1,4 +1,15 @@
|
|||
from django.contrib import admin
|
||||
from .models import StudentStatus
|
||||
from leaflet.admin import LeafletGeoAdmin
|
||||
|
||||
admin.site.register(StudentStatus)
|
||||
|
||||
class StudentStatusAdmin(LeafletGeoAdmin):
|
||||
# define which fields are required
|
||||
def get_form(self, request, obj=None, **kwargs):
|
||||
form = super(StudentStatusAdmin, self).get_form(request, obj, **kwargs)
|
||||
form.base_fields['landmark'].required = False
|
||||
return form
|
||||
|
||||
|
||||
# Register the new StudentStatus model
|
||||
admin.site.register(StudentStatus, StudentStatusAdmin)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
# Generated by Django 4.2.2 on 2023-06-27 15:21
|
||||
# Generated by Django 4.2.3 on 2023-07-18 07:43
|
||||
|
||||
from django.conf import settings
|
||||
import django.contrib.gis.db.models.fields
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
@ -11,6 +12,7 @@ class Migration(migrations.Migration):
|
|||
|
||||
dependencies = [
|
||||
('accounts', '0002_initial'),
|
||||
('landmarks', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
|
@ -18,10 +20,10 @@ class Migration(migrations.Migration):
|
|||
name='StudentStatus',
|
||||
fields=[
|
||||
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, primary_key=True, serialize=False, to=settings.AUTH_USER_MODEL)),
|
||||
('x', models.FloatField(null=True)),
|
||||
('y', models.FloatField(null=True)),
|
||||
('location', django.contrib.gis.db.models.fields.PointField(blank=True, null=True, srid=4326)),
|
||||
('active', models.BooleanField(default=False)),
|
||||
('timestamp', models.DateField(auto_now_add=True)),
|
||||
('landmark', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='landmarks.landmark')),
|
||||
],
|
||||
),
|
||||
]
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Generated by Django 4.2.2 on 2023-06-27 15:21
|
||||
# Generated by Django 4.2.3 on 2023-07-18 07:43
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
@ -9,20 +9,20 @@ class Migration(migrations.Migration):
|
|||
initial = True
|
||||
|
||||
dependencies = [
|
||||
('study_groups', '0001_initial'),
|
||||
('student_status', '0001_initial'),
|
||||
('subjects', '0001_initial'),
|
||||
('study_groups', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='studentstatus',
|
||||
name='study_group',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='study_groups.studygroup'),
|
||||
field=models.ManyToManyField(blank=True, through='study_groups.StudyGroupMembership', to='study_groups.studygroup'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='studentstatus',
|
||||
name='subject',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='subjects.subject'),
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='subjects.subject'),
|
||||
),
|
||||
]
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
# Generated by Django 4.2.2 on 2023-06-27 15:53
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('study_groups', '0001_initial'),
|
||||
('student_status', '0002_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='studentstatus',
|
||||
name='study_group',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='studentstatus',
|
||||
name='study_group',
|
||||
field=models.ManyToManyField(blank=True, null=True, through='study_groups.StudyGroupMembership', to='study_groups.studygroup'),
|
||||
),
|
||||
]
|
|
@ -1,19 +0,0 @@
|
|||
# Generated by Django 4.2.2 on 2023-06-27 17:15
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('study_groups', '0001_initial'),
|
||||
('student_status', '0003_remove_studentstatus_study_group_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='studentstatus',
|
||||
name='study_group',
|
||||
field=models.ManyToManyField(blank=True, through='study_groups.StudyGroupMembership', to='study_groups.studygroup'),
|
||||
),
|
||||
]
|
|
@ -1,20 +0,0 @@
|
|||
# Generated by Django 4.2.2 on 2023-07-04 10:01
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('subjects', '0002_subjectstudent_subject_students'),
|
||||
('student_status', '0004_alter_studentstatus_study_group'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='studentstatus',
|
||||
name='subject',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='subjects.subject'),
|
||||
),
|
||||
]
|
|
@ -1,18 +1,23 @@
|
|||
from django.db import models
|
||||
from accounts.models import CustomUser
|
||||
from study_groups.models import StudyGroup
|
||||
|
||||
from django.contrib.gis.db import models as gis_models
|
||||
from django.contrib.gis.geos import Point
|
||||
# Create your models here.
|
||||
|
||||
|
||||
class StudentStatus(models.Model):
|
||||
user = models.OneToOneField(
|
||||
CustomUser, on_delete=models.CASCADE, primary_key=True)
|
||||
x = models.FloatField(null=True)
|
||||
y = models.FloatField(null=True)
|
||||
location = gis_models.PointField(blank=True, null=True, srid=4326)
|
||||
subject = models.ForeignKey(
|
||||
'subjects.Subject', on_delete=models.SET_NULL, null=True)
|
||||
active = models.BooleanField(default=False)
|
||||
timestamp = models.DateField(auto_now_add=True)
|
||||
landmark = models.ForeignKey(
|
||||
'landmarks.Landmark', on_delete=models.SET_NULL, null=True)
|
||||
study_group = models.ManyToManyField(
|
||||
'study_groups.StudyGroup', through='study_groups.StudyGroupMembership', blank=True)
|
||||
|
||||
def __str__(self):
|
||||
return self.user.full_name
|
||||
|
|
|
@ -1,18 +1,23 @@
|
|||
from rest_framework import serializers
|
||||
from .models import StudentStatus
|
||||
from subjects.models import Subject
|
||||
from django.contrib.gis.geos import Point
|
||||
from drf_extra_fields.geo_fields import PointField
|
||||
from landmarks.models import Landmark
|
||||
|
||||
|
||||
class StudentStatusSerializer(serializers.ModelSerializer):
|
||||
year_level = serializers.CharField(
|
||||
source='user.year_level', read_only=True)
|
||||
course = serializers.CharField(source='user.course', read_only=True)
|
||||
semester = serializers.CharField(source='user.semester', read_only=True)
|
||||
subject = serializers.SlugRelatedField(
|
||||
queryset=Subject.objects.all(), slug_field='name', required=True)
|
||||
user = serializers.CharField(source='user.full_name', read_only=True)
|
||||
location = PointField()
|
||||
landmark = serializers.SlugRelatedField(
|
||||
queryset=Landmark.objects.all(), many=False, slug_field='name', required=False, allow_null=True)
|
||||
|
||||
class Meta:
|
||||
model = StudentStatus
|
||||
fields = '__all__'
|
||||
read_only_fields = ['user']
|
||||
read_only_fields = ['user', 'landmark']
|
||||
|
||||
def create(self, validated_data):
|
||||
user = self.context['request'].user
|
||||
|
@ -24,8 +29,14 @@ class StudentStatusSerializer(serializers.ModelSerializer):
|
|||
active = validated_data.get('active', None)
|
||||
|
||||
if active is not None and active is False:
|
||||
validated_data['x'] = None
|
||||
validated_data['y'] = None
|
||||
validated_data['location'] = Point(0, 0)
|
||||
validated_data['subject'] = None
|
||||
validated_data['landmark'] = None
|
||||
else:
|
||||
# Check each landmark to see if our location is within it
|
||||
for landmark in Landmark.objects.all():
|
||||
if landmark.location.contains(validated_data['location']):
|
||||
validated_data['landmark'] = landmark
|
||||
break
|
||||
|
||||
return super().update(instance, validated_data)
|
||||
|
|
|
@ -19,4 +19,4 @@ class ActiveStudentStatusListAPIView(generics.ListAPIView):
|
|||
|
||||
def get_queryset(self):
|
||||
user = self.request.user
|
||||
return StudentStatus.objects.filter(active=True).exclude(user=user)
|
||||
return StudentStatus.objects.filter(active=True)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
from django.contrib import admin
|
||||
from .models import StudyGroup, StudyGroupMembership
|
||||
from leaflet.admin import LeafletGeoAdmin
|
||||
|
||||
|
||||
admin.site.register(StudyGroup)
|
||||
admin.site.register(StudyGroup, LeafletGeoAdmin)
|
||||
admin.site.register(StudyGroupMembership)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
# Generated by Django 4.2.2 on 2023-06-27 15:21
|
||||
# Generated by Django 4.2.3 on 2023-07-18 07:43
|
||||
|
||||
import django.contrib.gis.db.models.fields
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
@ -19,8 +20,7 @@ class Migration(migrations.Migration):
|
|||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=48)),
|
||||
('x', models.FloatField(null=True)),
|
||||
('y', models.FloatField(null=True)),
|
||||
('location', django.contrib.gis.db.models.fields.PointField(blank=True, null=True, srid=4326)),
|
||||
('active', models.BooleanField(default=False)),
|
||||
('timestamp', models.DateField(auto_now_add=True)),
|
||||
('subject', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='subjects.subject')),
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
from django.db import models
|
||||
from subjects.models import Subject
|
||||
from django.contrib.gis.db import models as gis_models
|
||||
from django.contrib.gis.geos import Point
|
||||
# Create your models here.
|
||||
|
||||
|
||||
|
@ -7,12 +9,14 @@ class StudyGroup(models.Model):
|
|||
name = models.CharField(max_length=48)
|
||||
users = models.ManyToManyField(
|
||||
'student_status.StudentStatus', through='StudyGroupMembership')
|
||||
x = models.FloatField(null=True)
|
||||
y = models.FloatField(null=True)
|
||||
location = gis_models.PointField(blank=True, null=True, srid=4326)
|
||||
subject = models.ForeignKey(Subject, on_delete=models.CASCADE)
|
||||
active = models.BooleanField(default=False)
|
||||
timestamp = models.DateField(auto_now_add=True)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class StudyGroupMembership(models.Model):
|
||||
user = models.ForeignKey(
|
||||
|
@ -21,4 +25,4 @@ class StudyGroupMembership(models.Model):
|
|||
'study_groups.StudyGroup', on_delete=models.CASCADE)
|
||||
|
||||
def __str__(self):
|
||||
return f'StudyGroupMembership: User={self.user_id}, StudyGroup={self.study_group_id}'
|
||||
return f'StudyGroupMembership: User={self.user}, StudyGroup={self.study_group.name}'
|
||||
|
|
|
@ -2,6 +2,8 @@ from rest_framework import serializers
|
|||
from .models import StudyGroup, StudyGroupMembership
|
||||
from accounts.models import CustomUser
|
||||
from subjects.models import Subject
|
||||
from drf_extra_fields.geo_fields import PointField
|
||||
from landmarks.models import Landmark
|
||||
|
||||
|
||||
class StudyGroupSerializer(serializers.ModelSerializer):
|
||||
|
@ -9,10 +11,29 @@ class StudyGroupSerializer(serializers.ModelSerializer):
|
|||
queryset=CustomUser.objects.all(), many=True, slug_field='name', required=False, allow_null=True)
|
||||
subject = serializers.SlugRelatedField(
|
||||
many=False, slug_field='name', queryset=Subject.objects.all(), required=True, allow_null=False)
|
||||
location = PointField()
|
||||
landmark = serializers.SlugRelatedField(
|
||||
queryset=Landmark.objects.all(), many=False, slug_field='name', required=False, allow_null=True)
|
||||
|
||||
def create(self, validated_data):
|
||||
user = self.context['request'].user
|
||||
study_group = StudyGroup.objects.create(
|
||||
users=[user], defaults=validated_data)
|
||||
validated_data['location'].read_only = True
|
||||
return study_group
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
# Check each landmark to see if our location is within it
|
||||
for landmark in Landmark.objects.all():
|
||||
if landmark.location.contains(validated_data['location']):
|
||||
validated_data['landmark'] = landmark
|
||||
break
|
||||
return super().update(instance, validated_data)
|
||||
|
||||
class Meta:
|
||||
model = StudyGroup
|
||||
fields = '__all__'
|
||||
read_only_fields = ['landmark']
|
||||
|
||||
|
||||
class StudyGroupMembershipSerializer(serializers.ModelSerializer):
|
||||
|
|
|
@ -4,7 +4,7 @@ from rest_framework.exceptions import PermissionDenied
|
|||
from rest_framework.permissions import IsAuthenticated
|
||||
from .serializers import StudyGroupSerializer
|
||||
from .models import StudyGroup
|
||||
from courses.models import SubjectCourse
|
||||
from subjects.models import SubjectCourse
|
||||
# Create your views here.
|
||||
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Generated by Django 4.2.2 on 2023-06-27 15:24
|
||||
# Generated by Django 4.2.3 on 2023-07-18 07:43
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
@ -20,7 +20,7 @@ class Migration(migrations.Migration):
|
|||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('message_content', models.TextField(max_length=1024)),
|
||||
('timestamp', models.DateField(auto_now_add=True)),
|
||||
('timestamp', models.DateTimeField(auto_now_add=True)),
|
||||
('study_group', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='study_groups.studygroup')),
|
||||
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
# Generated by Django 4.2.2 on 2023-06-27 17:15
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('studygroup_messages', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='message',
|
||||
name='timestamp',
|
||||
field=models.DateTimeField(auto_now_add=True),
|
||||
),
|
||||
]
|
|
@ -9,3 +9,6 @@ class Message(models.Model):
|
|||
study_group = models.ForeignKey(StudyGroup, on_delete=models.CASCADE)
|
||||
message_content = models.TextField(max_length=1024)
|
||||
timestamp = models.DateTimeField(auto_now_add=True)
|
||||
|
||||
def __str__(self):
|
||||
return f'Message: User={self.user.full_name}, Study_group={self.study_group.name}, ID={self.id}'
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
from django.contrib import admin
|
||||
from courses.models import Course
|
||||
from .models import Subject, SubjectStudent
|
||||
from .models import Subject, SubjectCourse, SubjectSemester, SubjectYearLevel
|
||||
|
||||
|
||||
class SubjectAdmin(admin.ModelAdmin):
|
||||
|
@ -8,4 +7,6 @@ class SubjectAdmin(admin.ModelAdmin):
|
|||
|
||||
|
||||
admin.site.register(Subject, SubjectAdmin)
|
||||
admin.site.register(SubjectStudent)
|
||||
admin.site.register(SubjectCourse)
|
||||
admin.site.register(SubjectSemester)
|
||||
admin.site.register(SubjectYearLevel)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
# Generated by Django 4.2.2 on 2023-06-27 15:21
|
||||
# Generated by Django 4.2.3 on 2023-07-18 07:43
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
@ -10,8 +11,9 @@ class Migration(migrations.Migration):
|
|||
|
||||
dependencies = [
|
||||
('semesters', '0001_initial'),
|
||||
('year_levels', '0001_initial'),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('courses', '0001_initial'),
|
||||
('year_levels', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
|
@ -21,9 +23,50 @@ class Migration(migrations.Migration):
|
|||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=64)),
|
||||
('code', models.CharField(max_length=16)),
|
||||
('courses', models.ManyToManyField(related_name='SubjectCourse_subject', through='courses.SubjectCourse', to='courses.course')),
|
||||
('semester', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='semesters.semester')),
|
||||
('year_level', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='Year_Level_name', to='year_levels.year_level')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='SubjectYearLevel',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('subject', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='subjects.subject')),
|
||||
('year_level', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='year_levels.year_level')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='SubjectSemester',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('semester', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='semesters.semester')),
|
||||
('subject', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='subjects.subject')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='SubjectCourse',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('course', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='courses.course')),
|
||||
('subject', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='subjects.subject')),
|
||||
],
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='subject',
|
||||
name='courses',
|
||||
field=models.ManyToManyField(related_name='SubjectCourse_subject', through='subjects.SubjectCourse', to='courses.course'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='subject',
|
||||
name='semesters',
|
||||
field=models.ManyToManyField(related_name='SubjectSemester_subject', through='subjects.SubjectSemester', to='semesters.semester'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='subject',
|
||||
name='students',
|
||||
field=models.ManyToManyField(to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='subject',
|
||||
name='year_levels',
|
||||
field=models.ManyToManyField(related_name='SubjectYearLevel_subject', through='subjects.SubjectYearLevel', to='year_levels.year_level'),
|
||||
),
|
||||
]
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
# Generated by Django 4.2.3 on 2023-07-18 10:28
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('year_levels', '0002_alter_year_level_name_alter_year_level_shortname'),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('courses', '0003_alter_course_name_alter_course_shortname'),
|
||||
('semesters', '0002_alter_semester_name_alter_semester_shortname'),
|
||||
('subjects', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='subject',
|
||||
name='code',
|
||||
field=models.CharField(max_length=16, unique=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='subject',
|
||||
name='name',
|
||||
field=models.CharField(max_length=64, unique=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='subject',
|
||||
name='students',
|
||||
field=models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='subjectcourse',
|
||||
name='course',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='courses.course', to_field='name'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='subjectcourse',
|
||||
name='subject',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='subjects.subject', to_field='name'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='subjectsemester',
|
||||
name='semester',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='semesters.semester', to_field='name'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='subjectsemester',
|
||||
name='subject',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='subjects.subject', to_field='name'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='subjectyearlevel',
|
||||
name='subject',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='subjects.subject', to_field='name'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='subjectyearlevel',
|
||||
name='year_level',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='year_levels.year_level', to_field='name'),
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='subjectcourse',
|
||||
unique_together={('subject', 'course')},
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='subjectsemester',
|
||||
unique_together={('subject', 'semester')},
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='subjectyearlevel',
|
||||
unique_together={('subject', 'year_level')},
|
||||
),
|
||||
]
|
|
@ -1,29 +0,0 @@
|
|||
# Generated by Django 4.2.2 on 2023-06-28 03:09
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('subjects', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='SubjectStudent',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('subject', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='subjects.subject')),
|
||||
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='subject',
|
||||
name='students',
|
||||
field=models.ManyToManyField(related_name='SubjectStudent_subject', through='subjects.SubjectStudent', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,29 @@
|
|||
# Generated by Django 4.2.3 on 2023-07-19 07:04
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('subjects', '0002_alter_subject_code_alter_subject_name_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='SubjectCode',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('code', models.CharField(max_length=16, unique=True)),
|
||||
],
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='subject',
|
||||
name='code',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='subject',
|
||||
name='code',
|
||||
field=models.ManyToManyField(to='subjects.subjectcode'),
|
||||
),
|
||||
]
|
18
stude/subjects/migrations/0004_rename_code_subject_codes.py
Normal file
18
stude/subjects/migrations/0004_rename_code_subject_codes.py
Normal file
|
@ -0,0 +1,18 @@
|
|||
# Generated by Django 4.2.3 on 2023-07-19 07:09
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('subjects', '0003_subjectcode_remove_subject_code_subject_code'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RenameField(
|
||||
model_name='subject',
|
||||
old_name='code',
|
||||
new_name='codes',
|
||||
),
|
||||
]
|
|
@ -1,38 +1,168 @@
|
|||
|
||||
import os
|
||||
import csv
|
||||
from django.conf import settings
|
||||
from django.db import models
|
||||
from django.db.models.signals import post_migrate
|
||||
from django.dispatch import receiver
|
||||
from courses.models import Course
|
||||
from year_levels.models import Year_Level
|
||||
from semesters.models import Semester
|
||||
# Create your models here.
|
||||
|
||||
|
||||
class Subject(models.Model):
|
||||
name = models.CharField(max_length=64)
|
||||
code = models.CharField(max_length=16)
|
||||
name = models.CharField(max_length=64, unique=True)
|
||||
codes = models.ManyToManyField(
|
||||
'subjects.SubjectCode')
|
||||
courses = models.ManyToManyField(
|
||||
'courses.Course', through='courses.SubjectCourse', related_name='SubjectCourse_subject')
|
||||
'courses.Course', through='subjects.SubjectCourse', related_name='SubjectCourse_subject')
|
||||
students = models.ManyToManyField(
|
||||
'accounts.CustomUser', through='subjects.SubjectStudent', related_name='SubjectStudent_subject')
|
||||
'accounts.CustomUser', blank=True)
|
||||
|
||||
year_level = models.ForeignKey(
|
||||
Year_Level,
|
||||
on_delete=models.SET_NULL,
|
||||
null=True,
|
||||
related_name='Year_Level_name'
|
||||
)
|
||||
semester = models.ForeignKey(
|
||||
Semester,
|
||||
on_delete=models.SET_NULL,
|
||||
null=True
|
||||
)
|
||||
year_levels = models.ManyToManyField(
|
||||
'year_levels.Year_Level', through='subjects.SubjectYearLevel', related_name='SubjectYearLevel_subject')
|
||||
|
||||
semesters = models.ManyToManyField(
|
||||
'semesters.Semester', through='subjects.SubjectSemester', related_name='SubjectSemester_subject')
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
code_list = ', '.join(self.codes.values_list('code', flat=True))
|
||||
return f'{self.name} ({code_list})'
|
||||
|
||||
|
||||
class SubjectStudent(models.Model):
|
||||
user = models.ForeignKey(
|
||||
'accounts.CustomUser', on_delete=models.CASCADE)
|
||||
class SubjectCode(models.Model):
|
||||
code = models.CharField(max_length=16, unique=True)
|
||||
|
||||
def __str__(self):
|
||||
return self.code
|
||||
|
||||
|
||||
class SubjectCourse(models.Model):
|
||||
subject = models.ForeignKey(
|
||||
'subjects.Subject', on_delete=models.CASCADE)
|
||||
'subjects.Subject', on_delete=models.CASCADE, to_field='name')
|
||||
course = models.ForeignKey(
|
||||
'courses.Course', on_delete=models.CASCADE, null=True, to_field='name')
|
||||
|
||||
def __str__(self):
|
||||
return f'User: User={self.user_id}, Subject={self.subject_name}'
|
||||
return f'Subject={self.subject.name}, Course={self.course.name}'
|
||||
|
||||
class Meta:
|
||||
unique_together = [['subject', 'course']]
|
||||
|
||||
|
||||
class SubjectYearLevel(models.Model):
|
||||
subject = models.ForeignKey(
|
||||
'subjects.Subject', on_delete=models.CASCADE, to_field='name')
|
||||
year_level = models.ForeignKey(
|
||||
'year_levels.Year_Level', on_delete=models.CASCADE, to_field='name')
|
||||
|
||||
def __str__(self):
|
||||
return f'Subject={self.subject.name}, Year Level={self.year_level.name}'
|
||||
|
||||
class Meta:
|
||||
unique_together = [['subject', 'year_level']]
|
||||
|
||||
|
||||
class SubjectSemester(models.Model):
|
||||
subject = models.ForeignKey(
|
||||
'subjects.Subject', on_delete=models.CASCADE, to_field='name')
|
||||
semester = models.ForeignKey(
|
||||
'semesters.Semester', on_delete=models.CASCADE, to_field='name')
|
||||
|
||||
def __str__(self):
|
||||
return f'Subject={self.subject.name}, Semester={self.semester.name}'
|
||||
|
||||
class Meta:
|
||||
unique_together = [['subject', 'semester']]
|
||||
|
||||
|
||||
# Create subjects on initial migrate
|
||||
@receiver(post_migrate)
|
||||
def populate_subjects(sender, **kwargs):
|
||||
if sender.name == 'subjects':
|
||||
root_path = os.path.join(settings.MEDIA_ROOT, 'records')
|
||||
csv_files = [f for f in os.listdir(root_path) if f.endswith('.csv')]
|
||||
|
||||
for csv_file in csv_files:
|
||||
csv_file_path = os.path.join(root_path, csv_file)
|
||||
# Filename contains course of subjects
|
||||
filename = os.path.splitext(csv_file)[0]
|
||||
print('Reading subjects from', filename)
|
||||
with open(csv_file_path, newline='') as csvfile:
|
||||
|
||||
reader = csv.reader(csvfile)
|
||||
next(reader) # Skip the header row
|
||||
subject_count = 0
|
||||
updated_subjects = 0
|
||||
ignored_subjects = 0
|
||||
for row in reader:
|
||||
if not any(row):
|
||||
continue
|
||||
|
||||
# Get subject information
|
||||
year_term = row[0].split('-')
|
||||
subject_year_level = year_term[0].strip()
|
||||
subject_semester = year_term[1].strip()
|
||||
subject_code = row[1]
|
||||
subject_name = row[2]
|
||||
|
||||
# Definitions of subjects to ignore
|
||||
ignored_subject_codes = ['NSTP', 'ROTC', 'CWTS', 'LTS']
|
||||
ignored_subject_names = [
|
||||
'PRACTICUM', 'On the Job Training', 'CAPSTONE', 'Capstone']
|
||||
|
||||
# Skip ignored subjects
|
||||
if any(ignored_code in subject_code for ignored_code in ignored_subject_codes):
|
||||
ignored_subjects += 1
|
||||
continue
|
||||
|
||||
if any(ignored_name in subject_name for ignored_name in ignored_subject_names):
|
||||
ignored_subjects += 1
|
||||
continue
|
||||
|
||||
# Get relevant info for specific subject
|
||||
course = Course.objects.filter(
|
||||
name=filename).first()
|
||||
year_level = Year_Level.objects.filter(
|
||||
name=subject_year_level).first()
|
||||
semester = Semester.objects.filter(
|
||||
name=subject_semester).first()
|
||||
|
||||
# If subject already exists with relevant info, skip over it
|
||||
if (Subject.objects.filter(name=subject_name, year_levels=year_level, semesters=semester).exists()):
|
||||
# print('Duplicate subject')
|
||||
continue
|
||||
|
||||
# Else if subject exists without relevant info, add relevant info
|
||||
if (Subject.objects.filter(name=subject_name).exists()):
|
||||
SUBJECT = Subject.objects.filter(name=subject_name
|
||||
).first()
|
||||
|
||||
SUBJECT.courses.add(course)
|
||||
SUBJECT.year_levels.add(year_level)
|
||||
SUBJECT.semesters.add(semester)
|
||||
SUBJECT_CODE = SubjectCode.objects.get_or_create(
|
||||
code=subject_code)
|
||||
SUBJECT.codes.add(SUBJECT_CODE[0])
|
||||
updated_subjects += 1
|
||||
|
||||
# If subject does not exist at all, then create new subject
|
||||
else:
|
||||
|
||||
SUBJECT = Subject.objects.get_or_create(
|
||||
name=subject_name,
|
||||
)
|
||||
SUBJECT[0].courses.set([course])
|
||||
SUBJECT[0].year_levels.set([year_level])
|
||||
SUBJECT[0].semesters.set([semester])
|
||||
SUBJECT_CODE = SubjectCode.objects.get_or_create(
|
||||
code=subject_code)
|
||||
SUBJECT[0].codes.add(SUBJECT_CODE[0])
|
||||
subject_count += 1
|
||||
|
||||
# Set the course, year level, and semester of the subject
|
||||
print('Added', subject_count, 'subjects from', filename,)
|
||||
print('Updated', updated_subjects, 'subjects from', filename)
|
||||
print('Ignored', ignored_subjects,
|
||||
'subjects from', filename, '\n')
|
||||
|
|
|
@ -1,23 +1,21 @@
|
|||
from rest_framework import serializers
|
||||
from .models import Subject
|
||||
from .models import Subject, SubjectCode
|
||||
from courses.models import Course
|
||||
from year_levels.serializers import YearLevelSerializer
|
||||
from semesters.serializers import SemesterSerializer
|
||||
from courses.serializers import CourseSerializer
|
||||
from year_levels.models import Year_Level
|
||||
from semesters.models import Semester
|
||||
from accounts.models import CustomUser
|
||||
|
||||
|
||||
class SubjectSerializer(serializers.ModelSerializer):
|
||||
year_level = serializers.SerializerMethodField()
|
||||
semester = serializers.SerializerMethodField()
|
||||
year_levels = serializers.SlugRelatedField(
|
||||
queryset=Year_Level.objects.all(), many=True, slug_field='name', allow_null=True)
|
||||
semesters = serializers.SlugRelatedField(
|
||||
queryset=Semester.objects.all(), many=True, slug_field='name', allow_null=True)
|
||||
courses = serializers.SlugRelatedField(
|
||||
queryset=Course.objects.all(), many=True, slug_field='name', allow_null=True)
|
||||
codes = serializers.SlugRelatedField(
|
||||
queryset=SubjectCode.objects.all(), many=True, slug_field='code', allow_null=False)
|
||||
|
||||
class Meta:
|
||||
model = Subject
|
||||
fields = ('name', 'code', 'courses', 'year_level', 'semester')
|
||||
|
||||
def get_year_level(self, obj):
|
||||
return obj.year_level.name
|
||||
|
||||
def get_semester(self, obj):
|
||||
return obj.semester.name
|
||||
fields = ('id', 'name', 'codes', 'courses', 'year_levels', 'semesters')
|
||||
|
|
|
@ -1,11 +1,8 @@
|
|||
from django.urls import include, path
|
||||
from .views import SubjectListView
|
||||
from .views import SubjectByYearSemesterView, SubjectByYearView
|
||||
|
||||
from .views import SubjectByYearSemesterView, SubjectListView
|
||||
from rest_framework import routers
|
||||
urlpatterns = [
|
||||
path('', SubjectListView.as_view()),
|
||||
path('<slug:year_slug>/',
|
||||
SubjectByYearView.as_view()),
|
||||
path('<slug:year_slug>/<slug:semester_slug>',
|
||||
path('<slug:course_slug>/<slug:year_slug>/<slug:semester_slug>',
|
||||
SubjectByYearSemesterView.as_view()),
|
||||
]
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from rest_framework import generics
|
||||
from rest_framework import generics, viewsets
|
||||
from .models import Subject
|
||||
from .serializers import SubjectSerializer
|
||||
from rest_framework.views import APIView
|
||||
|
@ -10,27 +10,13 @@ class SubjectListView(generics.ListAPIView):
|
|||
queryset = Subject.objects.all()
|
||||
|
||||
|
||||
class SubjectByYearView(generics.ListAPIView):
|
||||
queryset = Subject.objects.all()
|
||||
|
||||
def get(self, request, year_slug):
|
||||
# Retrieve the subjects based on year level and semester slugs
|
||||
subjects = Subject.objects.filter(
|
||||
year_level__shortname=year_slug)
|
||||
|
||||
# Serialize the subjects
|
||||
serializer = SubjectSerializer(subjects, many=True)
|
||||
|
||||
return Response(serializer.data)
|
||||
|
||||
|
||||
class SubjectByYearSemesterView(generics.ListAPIView):
|
||||
queryset = Subject.objects.all()
|
||||
|
||||
def get(self, request, year_slug, semester_slug):
|
||||
def get(self, request, course_slug, year_slug, semester_slug):
|
||||
# Retrieve the subjects based on year level and semester slugs
|
||||
subjects = Subject.objects.filter(
|
||||
year_level__shortname=year_slug, semester__shortname=semester_slug)
|
||||
courses__shortname=course_slug, year_levels__shortname=year_slug, semesters__shortname=semester_slug)
|
||||
|
||||
# Serialize the subjects
|
||||
serializer = SubjectSerializer(subjects, many=True)
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
<p>{% blocktrans %}You're receiving this email because you need to finish activation process on {{ site_name }}.{% endblocktrans %}</p>
|
||||
|
||||
<p>{% trans "Please go to the following page to activate your account in-app:" %}</p>
|
||||
<p><a href="{{ domain }}://{{ url|safe }}">{{ domain }}://--/{{ url|safe }}</a></p>
|
||||
<p><a href="{{domain}}://{{url}}">{{ domain }}://{{url}}</a></p>
|
||||
|
||||
<p>{% blocktrans %}Many thanks from the {{ site_name }} team{% endblocktrans %}</p>
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Generated by Django 4.2.2 on 2023-06-27 15:21
|
||||
# Generated by Django 4.2.3 on 2023-07-18 07:43
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
# Generated by Django 4.2.3 on 2023-07-18 10:28
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('year_levels', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='year_level',
|
||||
name='name',
|
||||
field=models.CharField(max_length=64, unique=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='year_level',
|
||||
name='shortname',
|
||||
field=models.CharField(max_length=16, unique=True),
|
||||
),
|
||||
]
|
|
@ -6,8 +6,8 @@ from django.dispatch import receiver
|
|||
|
||||
|
||||
class Year_Level(models.Model):
|
||||
name = models.CharField(max_length=64)
|
||||
shortname = models.CharField(max_length=16)
|
||||
name = models.CharField(max_length=64, unique=True)
|
||||
shortname = models.CharField(max_length=16, unique=True)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
|
Loading…
Reference in a new issue