diff --git a/Pipfile b/Pipfile index 283d4fd..d09bcc4 100644 --- a/Pipfile +++ b/Pipfile @@ -15,7 +15,7 @@ mkdocs-material = "*" black = "==19.10b0" [packages] -django = ">=>=1.11.28,<1.12" +django = ">2.2,<3" pillow = ">=6.2.2" requests = "*" django-taggit = "*" diff --git a/Pipfile.lock b/Pipfile.lock index 9dd3d58..b37b008 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "d51c9cbf51cc1544c7e94d9961f31d4be824a5be7659f7f6eb20cb6a7ad95570" + "sha256": "3babe4b48b5f1935fb8dcc75741e80190b3f6099e812405d17c8ada21edcc9fa" }, "pipfile-spec": 6, "requires": { @@ -18,10 +18,10 @@ "default": { "certifi": { "hashes": [ - "sha256:1d987a998c75633c40847cc966fcf5904906c920a7f17ef374f5aa4282abd304", - "sha256:51fcb31174be6e6664c5f69e3e1691a2d72a1a12e90f872cbdb1567eb47b6519" + "sha256:5930595817496dd21bb8dc35dad090f1c2cd0adfaf21204bf6732ca5d8ee34d3", + "sha256:8fc0819f1f30ba15bdb34cceffb9ef04d99f420f68eb75d901e9560b8749fc41" ], - "version": "==2020.4.5.1" + "version": "==2020.6.20" }, "chardet": { "hashes": [ @@ -47,11 +47,11 @@ }, "django": { "hashes": [ - "sha256:014e3392058d94f40569206a24523ce254d55ad2f9f46c6550b0fe2e4f94cf3f", - "sha256:4200aefb6678019a0acf0005cd14cfce3a5e6b9b90d06145fcdd2e474ad4329c" + "sha256:edf0ecf6657713b0435b6757e6069466925cae70d634a3283c96b80c01e06191", + "sha256:f2250bd35d0f6c23e930c544629934144e5dd39a4c06092e1050c731c1712ba8" ], "index": "pypi", - "version": "==1.11.29" + "version": "==2.2.14" }, "django-appconf": { "hashes": [ @@ -110,10 +110,10 @@ }, "idna": { "hashes": [ - "sha256:7588d1c14ae4c77d74036e8c22ff447b26d0fde8f007354fd48a7814db15b7cb", - "sha256:a068a21ceac8a4d63dbfd964670474107f541babbd2250d61922f029858365fa" + "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6", + "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0" ], - "version": "==2.9" + "version": "==2.10" }, "itypes": { "hashes": [ @@ -185,31 +185,35 @@ }, "pillow": { "hashes": [ - "sha256:04766c4930c174b46fd72d450674612ab44cca977ebbcc2dde722c6933290107", - "sha256:0e2a3bceb0fd4e0cb17192ae506d5f082b309ffe5fc370a5667959c9b2f85fa3", - "sha256:0f01e63c34f0e1e2580cc0b24e86a5ccbbfa8830909a52ee17624c4193224cd9", - "sha256:12e4bad6bddd8546a2f9771485c7e3d2b546b458ae8ff79621214119ac244523", - "sha256:1f694e28c169655c50bb89a3fa07f3b854d71eb47f50783621de813979ba87f3", - "sha256:3d25dd8d688f7318dca6d8cd4f962a360ee40346c15893ae3b95c061cdbc4079", - "sha256:4b02b9c27fad2054932e89f39703646d0c543f21d3cc5b8e05434215121c28cd", - "sha256:9744350687459234867cbebfe9df8f35ef9e1538f3e729adbd8fde0761adb705", - "sha256:a0b49960110bc6ff5fead46013bcb8825d101026d466f3a4de3476defe0fb0dd", - "sha256:ae2b270f9a0b8822b98655cb3a59cdb1bd54a34807c6c56b76dd2e786c3b7db3", - "sha256:b37bb3bd35edf53125b0ff257822afa6962649995cbdfde2791ddb62b239f891", - "sha256:b532bcc2f008e96fd9241177ec580829dee817b090532f43e54074ecffdcd97f", - "sha256:b67a6c47ed963c709ed24566daa3f95a18f07d3831334da570c71da53d97d088", - "sha256:b943e71c2065ade6fef223358e56c167fc6ce31c50bc7a02dd5c17ee4338e8ac", - "sha256:ccc9ad2460eb5bee5642eaf75a0438d7f8887d484490d5117b98edd7f33118b7", - "sha256:d23e2aa9b969cf9c26edfb4b56307792b8b374202810bd949effd1c6e11ebd6d", - "sha256:eaa83729eab9c60884f362ada982d3a06beaa6cc8b084cf9f76cae7739481dfa", - "sha256:ee94fce8d003ac9fd206496f2707efe9eadcb278d94c271f129ab36aa7181344", - "sha256:f455efb7a98557412dc6f8e463c1faf1f1911ec2432059fa3e582b6000fc90e2", - "sha256:f46e0e024346e1474083c729d50de909974237c72daca05393ee32389dabe457", - "sha256:f54be399340aa602066adb63a86a6a5d4f395adfdd9da2b9a0162ea808c7b276", - "sha256:f784aad988f12c80aacfa5b381ec21fd3f38f851720f652b9f33facc5101cf4d" + "sha256:0295442429645fa16d05bd567ef5cff178482439c9aad0411d3f0ce9b88b3a6f", + "sha256:06aba4169e78c439d528fdeb34762c3b61a70813527a2c57f0540541e9f433a8", + "sha256:09d7f9e64289cb40c2c8d7ad674b2ed6105f55dc3b09aa8e4918e20a0311e7ad", + "sha256:0a80dd307a5d8440b0a08bd7b81617e04d870e40a3e46a32d9c246e54705e86f", + "sha256:1ca594126d3c4def54babee699c055a913efb01e106c309fa6b04405d474d5ae", + "sha256:25930fadde8019f374400f7986e8404c8b781ce519da27792cbe46eabec00c4d", + "sha256:431b15cffbf949e89df2f7b48528be18b78bfa5177cb3036284a5508159492b5", + "sha256:52125833b070791fcb5710fabc640fc1df07d087fc0c0f02d3661f76c23c5b8b", + "sha256:5e51ee2b8114def244384eda1c82b10e307ad9778dac5c83fb0943775a653cd8", + "sha256:612cfda94e9c8346f239bf1a4b082fdd5c8143cf82d685ba2dba76e7adeeb233", + "sha256:6d7741e65835716ceea0fd13a7d0192961212fd59e741a46bbed7a473c634ed6", + "sha256:6edb5446f44d901e8683ffb25ebdfc26988ee813da3bf91e12252b57ac163727", + "sha256:725aa6cfc66ce2857d585f06e9519a1cc0ef6d13f186ff3447ab6dff0a09bc7f", + "sha256:8dad18b69f710bf3a001d2bf3afab7c432785d94fcf819c16b5207b1cfd17d38", + "sha256:94cf49723928eb6070a892cb39d6c156f7b5a2db4e8971cb958f7b6b104fb4c4", + "sha256:97f9e7953a77d5a70f49b9a48da7776dc51e9b738151b22dacf101641594a626", + "sha256:9ad7f865eebde135d526bb3163d0b23ffff365cf87e767c649550964ad72785d", + "sha256:a060cf8aa332052df2158e5a119303965be92c3da6f2d93b6878f0ebca80b2f6", + "sha256:c79f9c5fb846285f943aafeafda3358992d64f0ef58566e23484132ecd8d7d63", + "sha256:c92302a33138409e8f1ad16731568c55c9053eee71bb05b6b744067e1b62380f", + "sha256:d08b23fdb388c0715990cbc06866db554e1822c4bdcf6d4166cf30ac82df8c41", + "sha256:d350f0f2c2421e65fbc62690f26b59b0bcda1b614beb318c81e38647e0f673a1", + "sha256:ec29604081f10f16a7aea809ad42e27764188fc258b02259a03a8ff7ded3808d", + "sha256:edf31f1150778abd4322444c393ab9c7bd2af271dd4dafb4208fb613b1f3cdc9", + "sha256:f7e30c27477dffc3e85c2463b3e649f751789e0f6c8456099eea7ddd53be4a8a", + "sha256:ffe538682dc19cc542ae7c3e504fdf54ca7f86fb8a135e59dd6bc8627eae6cce" ], "index": "pypi", - "version": "==7.1.2" + "version": "==7.2.0" }, "psycopg2-binary": { "hashes": [ @@ -262,11 +266,11 @@ }, "requests": { "hashes": [ - "sha256:43999036bfa82904b6af1d99e4882b560e5e2c68e5c4b0aa03b655f3d7d73fee", - "sha256:b3f43d496c6daba4493e7c431722aeb7dbc6288f52a6e04e7b6023b0247817e6" + "sha256:b3559a131db72c33ee969480840fff4bb6dd111de7dd27c8ee1f820f4f00231b", + "sha256:fe75cc94a9443b9246fc7049224f75604b113c36acb93f87b80ed42c44cbb898" ], "index": "pypi", - "version": "==2.23.0" + "version": "==2.24.0" }, "rjsmin": { "hashes": [ @@ -293,6 +297,13 @@ ], "version": "==1.15.0" }, + "sqlparse": { + "hashes": [ + "sha256:022fb9c87b524d1f7862b3037e541f68597a730a8843245c349fc93e1643dc4e", + "sha256:e162203737712307dfe78860cc56c8da8a852ab2ee33750e33aeadf38d12c548" + ], + "version": "==0.3.1" + }, "uritemplate": { "hashes": [ "sha256:07620c3f3f8eed1f12600845892b0e036a2420acf513c53f7de0abd911a5894f", @@ -340,19 +351,19 @@ }, "django-extensions": { "hashes": [ - "sha256:2f81b618ba4d1b0e58603e25012e5c74f88a4b706e0022a3b21f24f0322a6ce6", - "sha256:b19182d101a441fe001c5753553a901e2ef3ff60e8fbbe38881eb4a61fdd17c4" + "sha256:6230898b1e1d5deb3ddab8335b2d270edb7afa4ef916a95e479a19fdfb0464cb", + "sha256:d5fcf8f3bab019487e07473c24453bccd5acfb4440f3ef36788294c307b09d4c" ], "index": "pypi", - "version": "==2.2.9" + "version": "==3.0.3" }, "flake8": { "hashes": [ - "sha256:c69ac1668e434d37a2d2880b3ca9aafd54b3a10a3ac1ab101d22f29e29cf8634", - "sha256:ccaa799ef9893cebe69fdfefed76865aeaefbb94cb8545617b2298786a4de9a5" + "sha256:15e351d19611c887e482fb960eae4d44845013cc142d42896e9862f775d8cf5c", + "sha256:f04b9fcbac03b0a3e58c0ab3a0ecc462e023a9faf046d57794184028123aa208" ], "index": "pypi", - "version": "==3.8.2" + "version": "==3.8.3" }, "future": { "hashes": [ @@ -362,11 +373,11 @@ }, "importlib-metadata": { "hashes": [ - "sha256:2a688cbaa90e0cc587f1df48bdc97a6eadccdcd9c35fb3f976a09e3b5016d90f", - "sha256:34513a8a0c4962bc66d35b359558fd8a5e10cd472d37aec5f66858addef32c1e" + "sha256:90bb658cdbbf6d1735b6341ce708fc7024a3e14e99ffdc5783edea9f9b077f83", + "sha256:dc15b2969b4ce36305c51eebe62d418ac7791e9a157911d58bfb1f9ccd8e2070" ], "markers": "python_version < '3.8'", - "version": "==1.6.0" + "version": "==1.7.0" }, "jinja2": { "hashes": [ @@ -377,17 +388,16 @@ }, "joblib": { "hashes": [ - "sha256:61e49189c84b3c5d99a969d314853f4d1d263316cc694bec17548ebaa9c47b6e", - "sha256:6825784ffda353cc8a1be573118085789e5b5d29401856b35b756645ab5aecb5" + "sha256:8f52bf24c64b608bf0b2563e0e47d6fcf516abc8cfafe10cfd98ad66d94f92d6", + "sha256:d348c5d4ae31496b2aa060d6d9b787864dd204f9480baaa52d18850cb43e9f49" ], - "version": "==0.15.1" + "version": "==0.16.0" }, "livereload": { "hashes": [ - "sha256:78d55f2c268a8823ba499305dcac64e28ddeb9a92571e12d543cd304faf5817b", - "sha256:89254f78d7529d7ea0a3417d224c34287ebfe266b05e67e51facaf82c27f0f66" + "sha256:d1eddcb5c5eb8d2ca1fa1f750e580da624c0f7fcb734aa5780dc81b7dcbd89be" ], - "version": "==2.6.1" + "version": "==2.6.2" }, "lunr": { "extras": [ @@ -462,11 +472,11 @@ }, "mkdocs-material": { "hashes": [ - "sha256:381d35fe2fc80773c6c94fe18622f29719ed15719f968b14c2a628a41489b9ab", - "sha256:c896bfb8d7c52caeac423aa5b210828c317aa7a0916ab02ee1ada242edc5c813" + "sha256:7cd0fabc336ef93c78693134a0f9ac62900a76f905489aa935bab0b50910c47b", + "sha256:bf34d5cfbb2a085187adfcb82e8fb3bfc3014860f8416c2656dc8e9666b82eb0" ], "index": "pypi", - "version": "==5.2.2" + "version": "==5.4.0" }, "mkdocs-material-extensions": { "hashes": [ @@ -542,29 +552,29 @@ }, "regex": { "hashes": [ - "sha256:1386e75c9d1574f6aa2e4eb5355374c8e55f9aac97e224a8a5a6abded0f9c927", - "sha256:27ff7325b297fb6e5ebb70d10437592433601c423f5acf86e5bc1ee2919b9561", - "sha256:329ba35d711e3428db6b45a53b1b13a0a8ba07cbbcf10bbed291a7da45f106c3", - "sha256:3a9394197664e35566242686d84dfd264c07b20f93514e2e09d3c2b3ffdf78fe", - "sha256:51f17abbe973c7673a61863516bdc9c0ef467407a940f39501e786a07406699c", - "sha256:579ea215c81d18da550b62ff97ee187b99f1b135fd894a13451e00986a080cad", - "sha256:70c14743320a68c5dac7fc5a0f685be63bc2024b062fe2aaccc4acc3d01b14a1", - "sha256:7e61be8a2900897803c293247ef87366d5df86bf701083b6c43119c7c6c99108", - "sha256:8044d1c085d49673aadb3d7dc20ef5cb5b030c7a4fa253a593dda2eab3059929", - "sha256:89d76ce33d3266173f5be80bd4efcbd5196cafc34100fdab814f9b228dee0fa4", - "sha256:99568f00f7bf820c620f01721485cad230f3fb28f57d8fbf4a7967ec2e446994", - "sha256:a7c37f048ec3920783abab99f8f4036561a174f1314302ccfa4e9ad31cb00eb4", - "sha256:c2062c7d470751b648f1cacc3f54460aebfc261285f14bc6da49c6943bd48bdd", - "sha256:c9bce6e006fbe771a02bda468ec40ffccbf954803b470a0345ad39c603402577", - "sha256:ce367d21f33e23a84fb83a641b3834dd7dd8e9318ad8ff677fbfae5915a239f7", - "sha256:ce450ffbfec93821ab1fea94779a8440e10cf63819be6e176eb1973a6017aff5", - "sha256:ce5cc53aa9fbbf6712e92c7cf268274eaff30f6bd12a0754e8133d85a8fb0f5f", - "sha256:d466967ac8e45244b9dfe302bbe5e3337f8dc4dec8d7d10f5e950d83b140d33a", - "sha256:d881c2e657c51d89f02ae4c21d9adbef76b8325fe4d5cf0e9ad62f850f3a98fd", - "sha256:e565569fc28e3ba3e475ec344d87ed3cd8ba2d575335359749298a0899fe122e", - "sha256:ea55b80eb0d1c3f1d8d784264a6764f931e172480a2f1868f2536444c5f01e01" + "sha256:0dc64ee3f33cd7899f79a8d788abfbec168410be356ed9bd30bbd3f0a23a7204", + "sha256:1269fef3167bb52631ad4fa7dd27bf635d5a0790b8e6222065d42e91bede4162", + "sha256:14a53646369157baa0499513f96091eb70382eb50b2c82393d17d7ec81b7b85f", + "sha256:3a3af27a8d23143c49a3420efe5b3f8cf1a48c6fc8bc6856b03f638abc1833bb", + "sha256:46bac5ca10fb748d6c55843a931855e2727a7a22584f302dd9bb1506e69f83f6", + "sha256:4c037fd14c5f4e308b8370b447b469ca10e69427966527edcab07f52d88388f7", + "sha256:51178c738d559a2d1071ce0b0f56e57eb315bcf8f7d4cf127674b533e3101f88", + "sha256:5ea81ea3dbd6767873c611687141ec7b06ed8bab43f68fad5b7be184a920dc99", + "sha256:6961548bba529cac7c07af2fd4d527c5b91bb8fe18995fed6044ac22b3d14644", + "sha256:75aaa27aa521a182824d89e5ab0a1d16ca207318a6b65042b046053cfc8ed07a", + "sha256:7a2dd66d2d4df34fa82c9dc85657c5e019b87932019947faece7983f2089a840", + "sha256:8a51f2c6d1f884e98846a0a9021ff6861bdb98457879f412fdc2b42d14494067", + "sha256:9c568495e35599625f7b999774e29e8d6b01a6fb684d77dee1f56d41b11b40cd", + "sha256:9eddaafb3c48e0900690c1727fba226c4804b8e6127ea409689c3bb492d06de4", + "sha256:bbb332d45b32df41200380fff14712cb6093b61bd142272a10b16778c418e98e", + "sha256:bc3d98f621898b4a9bc7fecc00513eec8f40b5b83913d74ccb445f037d58cd89", + "sha256:c11d6033115dc4887c456565303f540c44197f4fc1a2bfb192224a301534888e", + "sha256:c50a724d136ec10d920661f1442e4a8b010a4fe5aebd65e0c2241ea41dbe93dc", + "sha256:d0a5095d52b90ff38592bbdc2644f17c6d495762edf47d876049cfd2968fbccf", + "sha256:d6cff2276e502b86a25fd10c2a96973fdb45c7a977dca2138d661417f3728341", + "sha256:e46d13f38cfcbb79bfdb2964b0fe12561fe633caf964a77a5f8d4e45fe5d2ef7" ], - "version": "==2020.5.14" + "version": "==2020.7.14" }, "six": { "hashes": [ @@ -596,10 +606,10 @@ }, "tqdm": { "hashes": [ - "sha256:4733c4a10d0f2a4d098d801464bdaf5240c7dadd2a7fde4ee93b0a0efd9fb25e", - "sha256:acdafb20f51637ca3954150d0405ff1a7edde0ff19e38fb99a80a66210d2a28f" + "sha256:6baa75a88582b1db6d34ce4690da5501d2a1cb65c34664840a456b2c9f794d29", + "sha256:fcb7cb5b729b60a27f300b15c1ffd4744f080fb483b88f31dc8654b082cc8ea5" ], - "version": "==4.46.0" + "version": "==4.48.0" }, "typed-ast": { "hashes": [ diff --git a/core/migrations/0001_initial.py b/core/migrations/0001_initial.py index aa7b8d6..73d3810 100644 --- a/core/migrations/0001_initial.py +++ b/core/migrations/0001_initial.py @@ -36,12 +36,12 @@ class Migration(migrations.Migration): migrations.AddField( model_name='pin', name='image', - field=models.ForeignKey(related_name='pin', to='core.Image'), + field=models.ForeignKey(related_name='pin', to='core.Image', on_delete=models.CASCADE), ), migrations.AddField( model_name='pin', name='submitter', - field=models.ForeignKey(to='users.User'), + field=models.ForeignKey(to='users.User', on_delete=models.CASCADE), ), migrations.AddField( model_name='pin', diff --git a/core/models.py b/core/models.py index 5d8a60b..9edc3af 100644 --- a/core/models.py +++ b/core/models.py @@ -74,7 +74,7 @@ class Board(models.Model): unique_together = ("submitter", "name") index_together = ("submitter", "name") - submitter = models.ForeignKey(User) + submitter = models.ForeignKey(User, on_delete=models.CASCADE) name = models.CharField(max_length=128, blank=False, null=False) private = models.BooleanField(default=False, blank=False) pins = models.ManyToManyField("Pin", related_name="pins", blank=True) @@ -83,12 +83,12 @@ class Board(models.Model): class Pin(models.Model): - submitter = models.ForeignKey(User) + submitter = models.ForeignKey(User, on_delete=models.CASCADE) private = models.BooleanField(default=False, blank=False) url = models.CharField(null=True, blank=True, max_length=256) referer = models.CharField(null=True, blank=True, max_length=256) description = models.TextField(blank=True, null=True) - image = models.ForeignKey(Image, related_name='pin') + image = models.ForeignKey(Image, related_name='pin', on_delete=models.CASCADE) published = models.DateTimeField(auto_now_add=True) tags = TaggableManager() diff --git a/core/tests/api.py b/core/tests/api.py index 28703ab..6076e9b 100644 --- a/core/tests/api.py +++ b/core/tests/api.py @@ -55,16 +55,16 @@ class BoardPrivacyTests(APITestCase): def test_should_non_owner_and_anonymous_user_has_no_permission_to_list_private_board(self): resp = self.client.get(self.boards_url) - self.assertEqual(len(resp.data), 0, resp.data) + self.assertEqual(len(resp.json()), 0, resp.json()) self.client.login(username=self.non_owner.username, password='password') resp = self.client.get(self.boards_url) - self.assertEqual(len(resp.data), 0, resp.data) + self.assertEqual(len(resp.json()), 0, resp.content) def test_should_owner_has_permission_to_list_private_board(self): self.client.login(username=self.non_owner.username, password='password') resp = self.client.get(self.boards_url) - self.assertEqual(len(resp.data), 0, resp.data) + self.assertEqual(len(resp.json()), 0, resp.content) def test_should_non_owner_and_anonymous_user_has_no_permission_to_view_private_board(self): resp = self.client.get(self.board_url) @@ -106,35 +106,35 @@ class PinPrivacyTests(APITestCase): def test_should_non_owner_and_anonymous_user_has_no_permission_to_list_private_pin(self): resp = self.client.get(reverse("pin-list")) - self.assertEqual(len(resp.data['results']), 0, resp.data) + self.assertEqual(len(resp.json()['results']), 0, resp.content) self.client.login(username=self.non_owner.username, password='password') resp = self.client.get(reverse("pin-list")) - self.assertEqual(len(resp.data['results']), 0, resp.data) + self.assertEqual(len(resp.json()['results']), 0, resp.content) def test_should_non_owner_and_anonymous_user_has_no_permission_to_list_private_pin_in_board(self): resp = self.client.get(self.board_url) - self.assertEqual(len(resp.data['pins_detail']), 0, resp.data) + self.assertEqual(len(resp.json()['pins_detail']), 0, resp.content) self.client.login(username=self.non_owner.username, password='password') resp = self.client.get(self.board_url) - self.assertEqual(len(resp.data['pins_detail']), 0, resp.data) + self.assertEqual(len(resp.json()['pins_detail']), 0, resp.content) def test_should_owner_user_has_permission_to_list_private_pin_in_board(self): self.client.login(username=self.owner.username, password='password') resp = self.client.get(self.board_url) - self.assertEqual(len(resp.data['pins_detail']), 1, resp.data) + self.assertEqual(len(resp.json()['pins_detail']), 1, resp.content) def test_should_owner_user_has_permission_to_list_private_pin(self): self.client.login(username=self.owner.username, password='password') resp = self.client.get(reverse("pin-list")) - self.assertEqual(len(resp.data['results']), 1, resp.data) + self.assertEqual(len(resp.json()['results']), 1, resp.content) def test_should_owner_has_permission_to_view_private_pin(self): self.client.login(username=self.owner.username, password='password') resp = self.client.get(self.private_pin_url) self.assertEqual(resp.status_code, 200) - self.assertEqual(resp.data['id'], self.private_pin.id) + self.assertEqual(resp.json()['id'], self.private_pin.id) def test_should_anonymous_user_has_no_permission_to_view_private_pin(self): resp = self.client.get(self.private_pin_url) diff --git a/core/tests/views.py b/core/tests/views.py index 3489c56..2607423 100644 --- a/core/tests/views.py +++ b/core/tests/views.py @@ -1,8 +1,7 @@ -from django.core.urlresolvers import reverse from django.test import TestCase from core.models import Image -from core.tests import create_user +from core.tests import create_user, reverse from users.models import User @@ -25,7 +24,7 @@ class CreateImageTest(TestCase): self.assertEqual(response.json()['id'], image.pk) def test_post_error(self): - response = self.client.post(reverse('image-list'), {'image': None}) + response = self.client.post(reverse('image-list'), {'image': ''}) self.assertEqual( response.json(), { diff --git a/django_images/migrations/0001_initial.py b/django_images/migrations/0001_initial.py index e3f0f84..ac95ca6 100644 --- a/django_images/migrations/0001_initial.py +++ b/django_images/migrations/0001_initial.py @@ -28,7 +28,7 @@ class Migration(migrations.Migration): ('size', models.CharField(max_length=100)), ('height', models.PositiveIntegerField(default=0, editable=False)), ('width', models.PositiveIntegerField(default=0, editable=False)), - ('original', models.ForeignKey(to='django_images.Image')), + ('original', models.ForeignKey(to='django_images.Image', on_delete=models.CASCADE)), ], ), migrations.AlterUniqueTogether( diff --git a/django_images/models.py b/django_images/models.py index 1a05ec8..1ec17d4 100644 --- a/django_images/models.py +++ b/django_images/models.py @@ -3,13 +3,11 @@ import os.path from django.db import models from django.core.files.uploadedfile import InMemoryUploadedFile -from django.core.urlresolvers import reverse from django.dispatch import receiver -try: - from importlib import import_module -except ImportError: - from django.utils.importlib import import_module +from importlib import import_module + +from django.urls import reverse from . import utils from .settings import IMAGE_SIZES, IMAGE_PATH, IMAGE_AUTO_DELETE @@ -99,7 +97,7 @@ class ThumbnailManager(models.Manager): class Thumbnail(models.Model): - original = models.ForeignKey(Image) + original = models.ForeignKey(Image, on_delete=models.CASCADE) image = models.ImageField(upload_to=upload_to, height_field='height', width_field='width', max_length=255) diff --git a/django_images/tests.py b/django_images/tests.py index 8452577..4f4cbe6 100644 --- a/django_images/tests.py +++ b/django_images/tests.py @@ -1,9 +1,10 @@ +from io import BytesIO + import mock import qrcode from django.test import TestCase from django.core.files.images import ImageFile from django.conf import settings -from django.utils.six import BytesIO from django_images.models import Image, Thumbnail from django_images.templatetags.images import at_size from django_images.utils import scale_and_crop_single diff --git a/docker/nginx/sites-enabled/default b/docker/nginx/sites-enabled/default index 87a0457..a867851 100644 --- a/docker/nginx/sites-enabled/default +++ b/docker/nginx/sites-enabled/default @@ -12,6 +12,11 @@ server { expires max; access_log off; } + location /media { + alias /data/static/media; + expires max; + access_log off; + } location /api { proxy_set_header Host $host; diff --git a/docs/src/upgrade-guide.md b/docs/src/upgrade-guide.md new file mode 100644 index 0000000..e5caff3 --- /dev/null +++ b/docs/src/upgrade-guide.md @@ -0,0 +1,33 @@ +Upgrade Guide +--------------------- + +This doc is about how you should do to upgrade specified version to next version. + +Generally, you should have no extra action to take if you use our docker version +if we haven't written notes for it. + +How to get the current version: +``` +git tag +``` +The first line of output is our latest version of code. + + +# v2.0.2 -> v2.1.0 +Main breaking changes: + ++ Upgrade `django 1` to django `2.2 LTS` + +How to: + +If you use non-docker version, you should change your web-server config to add a new +alias for `media file path` (where to store images). + +Please add following config to your nginx config in `server` block: +``` +location /media { + alias /path/to/static/media; + expires max; + access_log off; +} +``` diff --git a/mkdocs.yml b/mkdocs.yml index c8eac7b..146bd98 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -20,6 +20,7 @@ nav: - Install with Docker: 'install-with-docker.md' - Development: 'development.md' - Plugin System: 'plugin-system.md' + - Upgrade Guide: 'upgrade-guide.md' - Docs: 'docs.md' - Passwords: 'passwords.md' - Assets: 'assets.md' diff --git a/pinry-spa/vue.config.js b/pinry-spa/vue.config.js index 712592a..7185f31 100644 --- a/pinry-spa/vue.config.js +++ b/pinry-spa/vue.config.js @@ -6,7 +6,7 @@ module.exports = { changeOrigin: true, ws: true, }, - '/static/media': { + '/media': { target: 'http://localhost:8000/', changeOrigin: true, }, diff --git a/pinry/middleware.py b/pinry/middleware.py index d3471ef..4b23336 100644 --- a/pinry/middleware.py +++ b/pinry/middleware.py @@ -1,7 +1,9 @@ from django.middleware.csrf import get_token +from django.utils.deprecation import MiddlewareMixin -class ForceCSRFCookieMiddleware: +class ForceCSRFCookieMiddleware(MiddlewareMixin): + def process_request(self, request): if "CSRF_TOKEN" not in request.META: get_token(request) diff --git a/pinry/settings/base.py b/pinry/settings/base.py index 9b9c313..700f6ce 100644 --- a/pinry/settings/base.py +++ b/pinry/settings/base.py @@ -26,7 +26,7 @@ INSTALLED_APPS = [ ROOT_URLCONF = 'pinry.urls' -MIDDLEWARE_CLASSES = [ +MIDDLEWARE = [ 'django.middleware.csrf.CsrfViewMiddleware', 'django.middleware.security.SecurityMiddleware', @@ -106,7 +106,7 @@ USE_TZ = True STATIC_URL = '/static/' -MEDIA_URL = '/static/media/' +MEDIA_URL = '/media/' # Set to False to disable people from creating new accounts. ALLOW_NEW_REGISTRATIONS = True diff --git a/pinry/urls.py b/pinry/urls.py index aae9654..7d44042 100644 --- a/pinry/urls.py +++ b/pinry/urls.py @@ -1,8 +1,8 @@ from django.conf import settings -from django.conf.urls import include, url +from django.conf.urls.static import static from django.contrib.staticfiles.urls import staticfiles_urlpatterns from django.contrib import admin -from django.views.static import serve +from django.urls import path, include from rest_framework.documentation import include_docs_urls from core.views import drf_router @@ -13,21 +13,19 @@ admin.autodiscover() urlpatterns = [ # drf api - url(r'^api/v2/', include(drf_router.urls)), - url(r'^api-auth/', include('rest_framework.urls', namespace="rest_framework")), - url(r'^api/v2/docs/', include_docs_urls(title='PinryAPI', schema_url='/')), + path('api/v2/', include(drf_router.urls)), + path('api-auth/', include('rest_framework.urls', namespace="rest_framework")), + path('api/v2/docs/', include_docs_urls(title='PinryAPI', schema_url='/')), # old api and views - url(r'^admin/', include(admin.site.urls)), - url(r'^api/v2/profile/', include('users.urls', namespace='users')), + path('admin/', admin.site.urls), + path('api/v2/profile/', include('users.urls')), ] if settings.DEBUG: urlpatterns += staticfiles_urlpatterns() - urlpatterns += [ - url(r'^media/(?P.*)$', serve, {'document_root': settings.MEDIA_ROOT, }), - ] + urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) if settings.IS_TEST: urlpatterns += staticfiles_urlpatterns() diff --git a/users/middleware.py b/users/middleware.py index 93f5daa..f78388a 100644 --- a/users/middleware.py +++ b/users/middleware.py @@ -1,15 +1,16 @@ from django.conf import settings from django.http import HttpResponseForbidden +from django.utils.deprecation import MiddlewareMixin -class Public(object): +class Public(MiddlewareMixin): acceptable_paths = ( "/api/v2/profile/", ) def process_request(self, request): - if settings.PUBLIC is False and not request.user.is_authenticated(): + if settings.PUBLIC is False and not request.user.is_authenticated: for path in self.acceptable_paths: if not request.path.startswith(path): return HttpResponseForbidden() diff --git a/users/tests.py b/users/tests.py index 3986fee..7149cb3 100644 --- a/users/tests.py +++ b/users/tests.py @@ -1,8 +1,8 @@ -from django.core.urlresolvers import reverse from django.test import TestCase from django.test.utils import override_settings import mock +from django.urls import reverse from .auth.backends import CombinedAuthBackend from .models import User diff --git a/users/urls.py b/users/urls.py index 5ec6619..515879b 100644 --- a/users/urls.py +++ b/users/urls.py @@ -3,6 +3,8 @@ from django.conf.urls import url, include from users.views import login_user from . import views + +app_name = "users" urlpatterns = [ url(r'', include(views.drf_router.urls)), url(r'^login/$', login_user, name='login'), diff --git a/users/views.py b/users/views.py index ce3dd21..fec9b4a 100644 --- a/users/views.py +++ b/users/views.py @@ -4,8 +4,8 @@ from django.conf import settings from django.contrib import messages from django.contrib.auth import authenticate, login, logout from django.contrib.auth.decorators import login_required -from django.core.urlresolvers import reverse from django.http import HttpResponseRedirect, HttpResponseBadRequest, HttpResponse +from django.urls import reverse from django.utils.functional import lazy from rest_framework import mixins, routers from rest_framework.permissions import BasePermission