From 1f9be8d7af57440e77e65fd8dc974cbab8e7b41b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Padilla?= Date: Tue, 14 Jan 2020 23:15:46 -0500 Subject: [PATCH] Add linting and pre-commit setup (#47) * Add linting setup * Run `pre-commit` on all files * Add GitHub Workflow to run lint checks * Update Dockerfile python version * Update README.md * Add runtime.txt for Heroku --- .flake8 | 2 +- .github/workflows/tests.yml | 18 ++ .isort.cfg | 9 + .pre-commit-config.yaml | 20 ++ Dockerfile | 4 +- Pipfile | 5 + Pipfile.lock | 228 +++++++++++++++++- README.md | 9 + manage.py | 15 +- runtime.txt | 1 + suministrospr/settings.py | 13 +- suministrospr/suministros/admin.py | 1 - suministrospr/suministros/forms.py | 2 +- .../management/commands/import_data.py | 3 +- .../suministros/migrations/0001_initial.py | 44 +++- .../migrations/0002_auto_20200113_2247.py | 6 +- .../migrations/0003_auto_20200113_2325.py | 90 ++++++- .../migrations/0004_suministro_slug.py | 12 +- suministrospr/suministros/models.py | 19 +- suministrospr/suministros/urls.py | 4 +- suministrospr/suministros/views.py | 6 +- suministrospr/urls.py | 1 - suministrospr/users/admin.py | 1 + .../users/migrations/0001_initial.py | 130 ++++++++-- .../migrations/0002_auto_20200113_2208.py | 10 +- suministrospr/utils/mixins.py | 2 +- suministrospr/wsgi.py | 8 +- 27 files changed, 567 insertions(+), 96 deletions(-) create mode 100644 .github/workflows/tests.yml create mode 100644 .isort.cfg create mode 100644 .pre-commit-config.yaml create mode 100644 runtime.txt diff --git a/.flake8 b/.flake8 index 5148f72..d389969 100644 --- a/.flake8 +++ b/.flake8 @@ -1,5 +1,5 @@ [flake8] -ignore = E203, E266, E501, W503 +ignore = E203, E266, E501, W503, E231 max-line-length = 88 max-complexity = 18 select = B,C,E,F,W,T4,B9 diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000..baa40fa --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,18 @@ +name: Build and test + +on: [push] + +jobs: + lint: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v1 + - name: Set up Python 3.8 + uses: actions/setup-python@v1 + with: + python-version: 3.8 + - name: Install pre-commit + run: pip install pre-commit + - name: Run pre-commit checks + run: pre-commit run --all-files diff --git a/.isort.cfg b/.isort.cfg new file mode 100644 index 0000000..268035f --- /dev/null +++ b/.isort.cfg @@ -0,0 +1,9 @@ +[settings] +atomic=True +multi_line_output=3 +include_trailing_comma=True +force_grid_wrap=0 +combine_as_imports=True +line_length=88 +skip=.venv,migrations +known_third_party = bleach,ckeditor,configurations,django,django_extensions,reversion,sentry_sdk diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..5199ac8 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,20 @@ +repos: + - repo: https://github.com/ambv/black + rev: 19.10b0 + hooks: + - id: black + + - repo: https://github.com/asottile/seed-isort-config + rev: v1.9.4 + hooks: + - id: seed-isort-config + + - repo: https://github.com/pre-commit/mirrors-isort + rev: v4.3.21 + hooks: + - id: isort + + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v2.4.0 + hooks: + - id: flake8 diff --git a/Dockerfile b/Dockerfile index a183ed9..7d606ac 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,8 +1,8 @@ -FROM python:3.7 +FROM python:3.8 ARG PIPENV_ARGS -ENV LANG en_US.utf8 +ENV LANG C.UTF-8 ENV PYTHONUNBUFFERED 1 # Add app user diff --git a/Pipfile b/Pipfile index 6a16cdf..9454ef6 100644 --- a/Pipfile +++ b/Pipfile @@ -5,6 +5,11 @@ name = "pypi" [dev-packages] Werkzeug = "==0.16.0" +black = "==19.10b0" +isort = "==4.3.21" +"flake8" = "==3.7.9" +pre-commit = "==1.21.0" +seed-isort-config = "==1.9.4" [packages] dj-database-url = "==0.5.0" diff --git a/Pipfile.lock b/Pipfile.lock index cb1d1b9..bd21a9b 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "66d67ec8c0b72c3918dcb816d1dabcc3b255ff63742c4b0718d12fe9a0c0670c" + "sha256": "d65f4749ddaf630d12951e5b4018cfc71454088102fe888c64d56a72776dc179" }, "pipfile-spec": 6, "requires": {}, @@ -206,6 +206,232 @@ } }, "develop": { + "appdirs": { + "hashes": [ + "sha256:9e5896d1372858f8dd3344faf4e5014d21849c756c8d5701f78f8a103b372d92", + "sha256:d8b24664561d0d34ddfaec54636d502d7cea6e29c3eaf68f3df6180863e2166e" + ], + "version": "==1.4.3" + }, + "aspy.refactor-imports": { + "hashes": [ + "sha256:6d465c18cadad7e5a87810ecf8e516cb6f78e91871f4f55d0f228c6c376bd16a", + "sha256:88418d9bd1a0d50b9d3836504469dce6f26ee8b2d78bd58b805d73dd8b381d55" + ], + "version": "==1.1.0" + }, + "aspy.yaml": { + "hashes": [ + "sha256:463372c043f70160a9ec950c3f1e4c3a82db5fca01d334b6bc89c7164d744bdc", + "sha256:e7c742382eff2caed61f87a39d13f99109088e5e93f04d76eb8d4b28aa143f45" + ], + "version": "==1.3.0" + }, + "attrs": { + "hashes": [ + "sha256:08a96c641c3a74e44eb59afb61a24f2cb9f4d7188748e76ba4bb5edfa3cb7d1c", + "sha256:f7b7ce16570fe9965acd6d30101a28f62fb4a7f9e926b3bbc9b61f8b04247e72" + ], + "version": "==19.3.0" + }, + "black": { + "hashes": [ + "sha256:1b30e59be925fafc1ee4565e5e08abef6b03fe455102883820fe5ee2e4734e0b", + "sha256:c2edb73a08e9e0e6f65a0e6af18b059b8b1cdd5bef997d7a0b181df93dc81539" + ], + "index": "pypi", + "version": "==19.10b0" + }, + "cached-property": { + "hashes": [ + "sha256:3a026f1a54135677e7da5ce819b0c690f156f37976f3e30c5430740725203d7f", + "sha256:9217a59f14a5682da7c4b8829deadbfc194ac22e9908ccf7c8820234e80a1504" + ], + "version": "==1.5.1" + }, + "cfgv": { + "hashes": [ + "sha256:edb387943b665bf9c434f717bf630fa78aecd53d5900d2e05da6ad6048553144", + "sha256:fbd93c9ab0a523bf7daec408f3be2ed99a980e20b2d19b50fc184ca6b820d289" + ], + "version": "==2.0.1" + }, + "click": { + "hashes": [ + "sha256:2335065e6395b9e67ca716de5f7526736bfa6ceead690adf616d925bdc622b13", + "sha256:5b94b49521f6456670fdb30cd82a4eca9412788a93fa6dd6df72c94d5a8ff2d7" + ], + "version": "==7.0" + }, + "entrypoints": { + "hashes": [ + "sha256:589f874b313739ad35be6e0cd7efde2a4e9b6fea91edcc34e58ecbb8dbe56d19", + "sha256:c70dd71abe5a8c85e55e12c19bd91ccfeec11a6e99044204511f9ed547d48451" + ], + "version": "==0.3" + }, + "flake8": { + "hashes": [ + "sha256:45681a117ecc81e870cbf1262835ae4af5e7a8b08e40b944a8a6e6b895914cfb", + "sha256:49356e766643ad15072a789a20915d3c91dc89fd313ccd71802303fd67e4deca" + ], + "index": "pypi", + "version": "==3.7.9" + }, + "identify": { + "hashes": [ + "sha256:418f3b2313ac0b531139311a6b426854e9cbdfcfb6175447a5039aa6291d8b30", + "sha256:8ad99ed1f3a965612dcb881435bf58abcfbeb05e230bb8c352b51e8eac103360" + ], + "version": "==1.4.10" + }, + "isort": { + "hashes": [ + "sha256:54da7e92468955c4fceacd0c86bd0ec997b0e1ee80d97f67c35a78b719dccab1", + "sha256:6e811fcb295968434526407adb8796944f1988c5b65e8139058f2014cbe100fd" + ], + "index": "pypi", + "version": "==4.3.21" + }, + "mccabe": { + "hashes": [ + "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42", + "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f" + ], + "version": "==0.6.1" + }, + "nodeenv": { + "hashes": [ + "sha256:561057acd4ae3809e665a9aaaf214afff110bbb6a6d5c8a96121aea6878408b3" + ], + "version": "==1.3.4" + }, + "pathspec": { + "hashes": [ + "sha256:163b0632d4e31cef212976cf57b43d9fd6b0bac6e67c26015d611a647d5e7424", + "sha256:562aa70af2e0d434367d9790ad37aed893de47f1693e4201fd1d3dca15d19b96" + ], + "version": "==0.7.0" + }, + "pre-commit": { + "hashes": [ + "sha256:8f48d8637bdae6fa70cc97db9c1dd5aa7c5c8bf71968932a380628c25978b850", + "sha256:f92a359477f3252452ae2e8d3029de77aec59415c16ae4189bcfba40b757e029" + ], + "index": "pypi", + "version": "==1.21.0" + }, + "pycodestyle": { + "hashes": [ + "sha256:95a2219d12372f05704562a14ec30bc76b05a5b297b21a5dfe3f6fac3491ae56", + "sha256:e40a936c9a450ad81df37f549d676d127b1b66000a6c500caa2b085bc0ca976c" + ], + "version": "==2.5.0" + }, + "pyflakes": { + "hashes": [ + "sha256:17dbeb2e3f4d772725c777fabc446d5634d1038f234e77343108ce445ea69ce0", + "sha256:d976835886f8c5b31d47970ed689944a0262b5f3afa00a5a7b4dc81e5449f8a2" + ], + "version": "==2.1.1" + }, + "pyyaml": { + "hashes": [ + "sha256:059b2ee3194d718896c0ad077dd8c043e5e909d9180f387ce42012662a4946d6", + "sha256:1cf708e2ac57f3aabc87405f04b86354f66799c8e62c28c5fc5f88b5521b2dbf", + "sha256:24521fa2890642614558b492b473bee0ac1f8057a7263156b02e8b14c88ce6f5", + "sha256:4fee71aa5bc6ed9d5f116327c04273e25ae31a3020386916905767ec4fc5317e", + "sha256:70024e02197337533eef7b85b068212420f950319cc8c580261963aefc75f811", + "sha256:74782fbd4d4f87ff04159e986886931456a1894c61229be9eaf4de6f6e44b99e", + "sha256:940532b111b1952befd7db542c370887a8611660d2b9becff75d39355303d82d", + "sha256:cb1f2f5e426dc9f07a7681419fe39cee823bb74f723f36f70399123f439e9b20", + "sha256:dbbb2379c19ed6042e8f11f2a2c66d39cceb8aeace421bfc29d085d93eda3689", + "sha256:e3a057b7a64f1222b56e47bcff5e4b94c4f61faac04c7c4ecb1985e18caa3994", + "sha256:e9f45bd5b92c7974e59bcd2dcc8631a6b6cc380a904725fce7bc08872e691615" + ], + "version": "==5.3" + }, + "regex": { + "hashes": [ + "sha256:07b39bf943d3d2fe63d46281d8504f8df0ff3fe4c57e13d1656737950e53e525", + "sha256:0932941cdfb3afcbc26cc3bcf7c3f3d73d5a9b9c56955d432dbf8bbc147d4c5b", + "sha256:0e182d2f097ea8549a249040922fa2b92ae28be4be4895933e369a525ba36576", + "sha256:10671601ee06cf4dc1bc0b4805309040bb34c9af423c12c379c83d7895622bb5", + "sha256:23e2c2c0ff50f44877f64780b815b8fd2e003cda9ce817a7fd00dea5600c84a0", + "sha256:26ff99c980f53b3191d8931b199b29d6787c059f2e029b2b0c694343b1708c35", + "sha256:27429b8d74ba683484a06b260b7bb00f312e7c757792628ea251afdbf1434003", + "sha256:3e77409b678b21a056415da3a56abfd7c3ad03da71f3051bbcdb68cf44d3c34d", + "sha256:4e8f02d3d72ca94efc8396f8036c0d3bcc812aefc28ec70f35bb888c74a25161", + "sha256:4eae742636aec40cf7ab98171ab9400393360b97e8f9da67b1867a9ee0889b26", + "sha256:6a6ae17bf8f2d82d1e8858a47757ce389b880083c4ff2498dba17c56e6c103b9", + "sha256:6a6ba91b94427cd49cd27764679024b14a96874e0dc638ae6bdd4b1a3ce97be1", + "sha256:7bcd322935377abcc79bfe5b63c44abd0b29387f267791d566bbb566edfdd146", + "sha256:98b8ed7bb2155e2cbb8b76f627b2fd12cf4b22ab6e14873e8641f266e0fb6d8f", + "sha256:bd25bb7980917e4e70ccccd7e3b5740614f1c408a642c245019cff9d7d1b6149", + "sha256:d0f424328f9822b0323b3b6f2e4b9c90960b24743d220763c7f07071e0778351", + "sha256:d58e4606da2a41659c84baeb3cfa2e4c87a74cec89a1e7c56bee4b956f9d7461", + "sha256:e3cd21cc2840ca67de0bbe4071f79f031c81418deb544ceda93ad75ca1ee9f7b", + "sha256:e6c02171d62ed6972ca8631f6f34fa3281d51db8b326ee397b9c83093a6b7242", + "sha256:e7c7661f7276507bce416eaae22040fd91ca471b5b33c13f8ff21137ed6f248c", + "sha256:ecc6de77df3ef68fee966bb8cb4e067e84d4d1f397d0ef6fce46913663540d77" + ], + "version": "==2020.1.8" + }, + "seed-isort-config": { + "hashes": [ + "sha256:81f7adf8dd0bc24e03d0f5eef87561e170757fc7a36050c01e4c29d150757783", + "sha256:cecccb911b8d01ecdca16e17d083bf4cd78e928db4d7906125b0373b81f1c7ec" + ], + "index": "pypi", + "version": "==1.9.4" + }, + "six": { + "hashes": [ + "sha256:1f1b7d42e254082a9db6279deae68afb421ceba6158efa6131de7b3003ee93fd", + "sha256:30f610279e8b2578cab6db20741130331735c781b56053c59c4076da27f06b66" + ], + "version": "==1.13.0" + }, + "toml": { + "hashes": [ + "sha256:229f81c57791a41d65e399fc06bf0848bab550a9dfd5ed66df18ce5f05e73d5c", + "sha256:235682dd292d5899d361a811df37e04a8828a5b1da3115886b73cf81ebc9100e" + ], + "version": "==0.10.0" + }, + "typed-ast": { + "hashes": [ + "sha256:0666aa36131496aed8f7be0410ff974562ab7eeac11ef351def9ea6fa28f6355", + "sha256:0c2c07682d61a629b68433afb159376e24e5b2fd4641d35424e462169c0a7919", + "sha256:249862707802d40f7f29f6e1aad8d84b5aa9e44552d2cc17384b209f091276aa", + "sha256:24995c843eb0ad11a4527b026b4dde3da70e1f2d8806c99b7b4a7cf491612652", + "sha256:269151951236b0f9a6f04015a9004084a5ab0d5f19b57de779f908621e7d8b75", + "sha256:4083861b0aa07990b619bd7ddc365eb7fa4b817e99cf5f8d9cf21a42780f6e01", + "sha256:498b0f36cc7054c1fead3d7fc59d2150f4d5c6c56ba7fb150c013fbc683a8d2d", + "sha256:4e3e5da80ccbebfff202a67bf900d081906c358ccc3d5e3c8aea42fdfdfd51c1", + "sha256:6daac9731f172c2a22ade6ed0c00197ee7cc1221aa84cfdf9c31defeb059a907", + "sha256:715ff2f2df46121071622063fc7543d9b1fd19ebfc4f5c8895af64a77a8c852c", + "sha256:73d785a950fc82dd2a25897d525d003f6378d1cb23ab305578394694202a58c3", + "sha256:8c8aaad94455178e3187ab22c8b01a3837f8ee50e09cf31f1ba129eb293ec30b", + "sha256:8ce678dbaf790dbdb3eba24056d5364fb45944f33553dd5869b7580cdbb83614", + "sha256:aaee9905aee35ba5905cfb3c62f3e83b3bec7b39413f0a7f19be4e547ea01ebb", + "sha256:bcd3b13b56ea479b3650b82cabd6b5343a625b0ced5429e4ccad28a8973f301b", + "sha256:c9e348e02e4d2b4a8b2eedb48210430658df6951fa484e59de33ff773fbd4b41", + "sha256:d205b1b46085271b4e15f670058ce182bd1199e56b317bf2ec004b6a44f911f6", + "sha256:d43943ef777f9a1c42bf4e552ba23ac77a6351de620aa9acf64ad54933ad4d34", + "sha256:d5d33e9e7af3b34a40dc05f498939f0ebf187f07c385fd58d591c533ad8562fe", + "sha256:fc0fea399acb12edbf8a628ba8d2312f583bdbdb3335635db062fa98cf71fca4", + "sha256:fe460b922ec15dd205595c9b5b99e2f056fd98ae8f9f56b888e7a17dc2b757e7" + ], + "version": "==1.4.1" + }, + "virtualenv": { + "hashes": [ + "sha256:0d62c70883c0342d59c11d0ddac0d954d0431321a41ab20851facf2b222598f3", + "sha256:55059a7a676e4e19498f1aad09b8313a38fcc0cdbe4fdddc0e9b06946d21b4bb" + ], + "version": "==16.7.9" + }, "werkzeug": { "hashes": [ "sha256:7280924747b5733b246fe23972186c6b348f9ae29724135a6dfc1e53cea433e7", diff --git a/README.md b/README.md index 6a7533c..749e584 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,15 @@ https://suministrospr.com ## Development ```bash +# Install pipenv (https://pipenv.kennethreitz.org/en/latest/install/#installing-pipenv) +$ pip install --user pipenv + +# Install project dependencies +$ pipenv install --dev + +# Install pre-commit hooks +$ pipenv run pre-commit install + $ cp example.env .env $ pipenv install --dev $ pipenv run python manage.py migrate diff --git a/manage.py b/manage.py index 3776aa1..53530ef 100755 --- a/manage.py +++ b/manage.py @@ -2,16 +2,17 @@ import os import sys -if __name__ == '__main__': - configuration = os.getenv('ENVIRONMENT', 'development').title() - os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'suministrospr.settings') - os.environ.setdefault('DJANGO_CONFIGURATION', configuration) +if __name__ == "__main__": + configuration = os.getenv("ENVIRONMENT", "development").title() + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "suministrospr.settings") + os.environ.setdefault("DJANGO_CONFIGURATION", configuration) try: from configurations.management import execute_from_command_line except ImportError as exc: raise ImportError( - 'Couldn\'t import Django. Are you sure it\'s installed and ' - 'available on your PYTHONPATH environment variable? Did you ' - 'forget to activate a virtual environment?') from exc + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) from exc execute_from_command_line(sys.argv) diff --git a/runtime.txt b/runtime.txt new file mode 100644 index 0000000..c5d7ce3 --- /dev/null +++ b/runtime.txt @@ -0,0 +1 @@ +python-3.8.1 diff --git a/suministrospr/settings.py b/suministrospr/settings.py index fcaabc9..6b6c99e 100644 --- a/suministrospr/settings.py +++ b/suministrospr/settings.py @@ -10,8 +10,8 @@ import os import sentry_sdk -from sentry_sdk.integrations.django import DjangoIntegration from configurations import Configuration, values +from sentry_sdk.integrations.django import DjangoIntegration class Common(Configuration): @@ -35,12 +35,10 @@ class Common(Configuration): "django.contrib.messages", "whitenoise.runserver_nostatic", "django.contrib.staticfiles", - "django_extensions", "debug_toolbar", "ckeditor", "reversion", - "suministrospr.users", "suministrospr.suministros", "suministrospr.utils", @@ -151,9 +149,7 @@ class Common(Configuration): def CACHES(self): if not self.REDIS_URL: return { - "default": { - "BACKEND": "django.core.cache.backends.locmem.LocMemCache" - } + "default": {"BACKEND": "django.core.cache.backends.locmem.LocMemCache"} } return { @@ -169,10 +165,7 @@ def post_setup(cls): super().post_setup() if cls.SENTRY_DSN: - sentry_sdk.init( - dsn=cls.SENTRY_DSN, - integrations=[DjangoIntegration()] - ) + sentry_sdk.init(dsn=cls.SENTRY_DSN, integrations=[DjangoIntegration()]) class Development(Common): diff --git a/suministrospr/suministros/admin.py b/suministrospr/suministros/admin.py index 7f97b42..22db235 100644 --- a/suministrospr/suministros/admin.py +++ b/suministrospr/suministros/admin.py @@ -1,5 +1,4 @@ from django.contrib import admin - from reversion.admin import VersionAdmin from .models import Suministro diff --git a/suministrospr/suministros/forms.py b/suministrospr/suministros/forms.py index e3101af..f0b8656 100644 --- a/suministrospr/suministros/forms.py +++ b/suministrospr/suministros/forms.py @@ -1,8 +1,8 @@ import bleach from django import forms -from .models import Suministro from .constants import ALLOWED_TAGS +from .models import Suministro class SuministroModelForm(forms.ModelForm): diff --git a/suministrospr/suministros/management/commands/import_data.py b/suministrospr/suministros/management/commands/import_data.py index a474498..100ae7f 100644 --- a/suministrospr/suministros/management/commands/import_data.py +++ b/suministrospr/suministros/management/commands/import_data.py @@ -1,7 +1,7 @@ import glob import json - import unicodedata + from django.core.management.base import BaseCommand from django.utils.text import slugify @@ -43,4 +43,3 @@ def handle(self, *args, **options): ) except EnvironmentError: self.stderr.write(f"There was an error reading file {file_path}") - diff --git a/suministrospr/suministros/migrations/0001_initial.py b/suministrospr/suministros/migrations/0001_initial.py index 273510b..1c972b7 100644 --- a/suministrospr/suministros/migrations/0001_initial.py +++ b/suministrospr/suministros/migrations/0001_initial.py @@ -1,7 +1,8 @@ # Generated by Django 2.2.9 on 2020-01-13 22:09 -from django.db import migrations, models import django.utils.timezone +from django.db import migrations, models + import suministrospr.utils.fields @@ -9,24 +10,41 @@ class Migration(migrations.Migration): initial = True - dependencies = [ - ] + dependencies = [] operations = [ migrations.CreateModel( - name='Suministro', + name="Suministro", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('created_at', suministrospr.utils.fields.DateTimeCreatedField(default=django.utils.timezone.now, editable=False)), - ('modified_at', suministrospr.utils.fields.DateTimeModifiedField(default=django.utils.timezone.now, editable=False)), - ('title', models.CharField(max_length=255)), - ('municipality', models.CharField(max_length=255)), - ('content', models.TextField()), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "created_at", + suministrospr.utils.fields.DateTimeCreatedField( + default=django.utils.timezone.now, editable=False + ), + ), + ( + "modified_at", + suministrospr.utils.fields.DateTimeModifiedField( + default=django.utils.timezone.now, editable=False + ), + ), + ("title", models.CharField(max_length=255)), + ("municipality", models.CharField(max_length=255)), + ("content", models.TextField()), ], options={ - 'ordering': ('-modified_at', '-created_at'), - 'get_latest_by': 'modified_at', - 'abstract': False, + "ordering": ("-modified_at", "-created_at"), + "get_latest_by": "modified_at", + "abstract": False, }, ), ] diff --git a/suministrospr/suministros/migrations/0002_auto_20200113_2247.py b/suministrospr/suministros/migrations/0002_auto_20200113_2247.py index 813085c..254ddef 100644 --- a/suministrospr/suministros/migrations/0002_auto_20200113_2247.py +++ b/suministrospr/suministros/migrations/0002_auto_20200113_2247.py @@ -7,13 +7,13 @@ class Migration(migrations.Migration): dependencies = [ - ('suministros', '0001_initial'), + ("suministros", "0001_initial"), ] operations = [ migrations.AlterField( - model_name='suministro', - name='content', + model_name="suministro", + name="content", field=ckeditor.fields.RichTextField(), ), ] diff --git a/suministrospr/suministros/migrations/0003_auto_20200113_2325.py b/suministrospr/suministros/migrations/0003_auto_20200113_2325.py index 7043ad8..786c5d1 100644 --- a/suministrospr/suministros/migrations/0003_auto_20200113_2325.py +++ b/suministrospr/suministros/migrations/0003_auto_20200113_2325.py @@ -6,13 +6,95 @@ class Migration(migrations.Migration): dependencies = [ - ('suministros', '0002_auto_20200113_2247'), + ("suministros", "0002_auto_20200113_2247"), ] operations = [ migrations.AlterField( - model_name='suministro', - name='municipality', - field=models.CharField(choices=[('adjuntas', 'Adjuntas'), ('aguada', 'Aguada'), ('aguadilla', 'Aguadilla'), ('aguas buenas', 'Aguas Buenas'), ('aibonito', 'Aibonito'), ('anasco', 'Anasco'), ('arecibo', 'Arecibo'), ('arroyo', 'Arroyo'), ('barceloneta', 'Barceloneta'), ('barranquitas', 'Barranquitas'), ('bayamon', 'Bayamon'), ('cabo rojo', 'Cabo Rojo'), ('caguas', 'Caguas'), ('camuy', 'Camuy'), ('canovanas', 'Canovanas'), ('carolina', 'Carolina'), ('catano', 'Catano'), ('cayey', 'Cayey'), ('ceiba', 'Ceiba'), ('ciales', 'Ciales'), ('cidra', 'Cidra'), ('coamo', 'Coamo'), ('comerio', 'Comerio'), ('corozal', 'Corozal'), ('culebra', 'Culebra'), ('dorado', 'Dorado'), ('fajardo', 'Fajardo'), ('florida', 'Florida'), ('guanica', 'Guanica'), ('guayama', 'Guayama'), ('guayanilla', 'Guayanilla'), ('guaynabo', 'Guaynabo'), ('gurabo', 'Gurabo'), ('hatillo', 'Hatillo'), ('hormigueros', 'Hormigueros'), ('humacao', 'Humacao'), ('isabela', 'Isabela'), ('jayuya', 'Jayuya'), ('juana diaz', 'Juana Diaz'), ('juncos', 'Juncos'), ('lajas', 'Lajas'), ('lares', 'Lares'), ('las marias', 'Las Marias'), ('las piedras', 'Las Piedras'), ('loiza', 'Loiza'), ('luquillo', 'Luquillo'), ('manati', 'Manati'), ('maricao', 'Maricao'), ('maunabo', 'Maunabo'), ('mayaguez', 'Mayaguez'), ('moca', 'Moca'), ('morovis', 'Morovis'), ('naguabo', 'Naguabo'), ('naranjito', 'Naranjito'), ('orocovis', 'Orocovis'), ('patillas', 'Patillas'), ('penuelas', 'Penuelas'), ('ponce', 'Ponce'), ('quebradillas', 'Quebradillas'), ('rincon', 'Rincon'), ('rio grande', 'Rio Grande'), ('sabana grande', 'Sabana Grande'), ('salinas', 'Salinas'), ('san german', 'San German'), ('san juan', 'San Juan'), ('san lorenzo', 'San Lorenzo'), ('san sebastian', 'San Sebastian'), ('santa isabel', 'Santa Isabel'), ('toa alta', 'Toa Alta'), ('toa baja', 'Toa Baja'), ('trujillo alto', 'Trujillo Alto'), ('utuado', 'Utuado'), ('vega alta', 'Vega Alta'), ('vega baja', 'Vega Baja'), ('vieques', 'Vieques'), ('villalba', 'Villalba'), ('yabucoa', 'Yabucoa'), ('yauco', 'Yauco')], max_length=255), + model_name="suministro", + name="municipality", + field=models.CharField( + choices=[ + ("adjuntas", "Adjuntas"), + ("aguada", "Aguada"), + ("aguadilla", "Aguadilla"), + ("aguas buenas", "Aguas Buenas"), + ("aibonito", "Aibonito"), + ("anasco", "Anasco"), + ("arecibo", "Arecibo"), + ("arroyo", "Arroyo"), + ("barceloneta", "Barceloneta"), + ("barranquitas", "Barranquitas"), + ("bayamon", "Bayamon"), + ("cabo rojo", "Cabo Rojo"), + ("caguas", "Caguas"), + ("camuy", "Camuy"), + ("canovanas", "Canovanas"), + ("carolina", "Carolina"), + ("catano", "Catano"), + ("cayey", "Cayey"), + ("ceiba", "Ceiba"), + ("ciales", "Ciales"), + ("cidra", "Cidra"), + ("coamo", "Coamo"), + ("comerio", "Comerio"), + ("corozal", "Corozal"), + ("culebra", "Culebra"), + ("dorado", "Dorado"), + ("fajardo", "Fajardo"), + ("florida", "Florida"), + ("guanica", "Guanica"), + ("guayama", "Guayama"), + ("guayanilla", "Guayanilla"), + ("guaynabo", "Guaynabo"), + ("gurabo", "Gurabo"), + ("hatillo", "Hatillo"), + ("hormigueros", "Hormigueros"), + ("humacao", "Humacao"), + ("isabela", "Isabela"), + ("jayuya", "Jayuya"), + ("juana diaz", "Juana Diaz"), + ("juncos", "Juncos"), + ("lajas", "Lajas"), + ("lares", "Lares"), + ("las marias", "Las Marias"), + ("las piedras", "Las Piedras"), + ("loiza", "Loiza"), + ("luquillo", "Luquillo"), + ("manati", "Manati"), + ("maricao", "Maricao"), + ("maunabo", "Maunabo"), + ("mayaguez", "Mayaguez"), + ("moca", "Moca"), + ("morovis", "Morovis"), + ("naguabo", "Naguabo"), + ("naranjito", "Naranjito"), + ("orocovis", "Orocovis"), + ("patillas", "Patillas"), + ("penuelas", "Penuelas"), + ("ponce", "Ponce"), + ("quebradillas", "Quebradillas"), + ("rincon", "Rincon"), + ("rio grande", "Rio Grande"), + ("sabana grande", "Sabana Grande"), + ("salinas", "Salinas"), + ("san german", "San German"), + ("san juan", "San Juan"), + ("san lorenzo", "San Lorenzo"), + ("san sebastian", "San Sebastian"), + ("santa isabel", "Santa Isabel"), + ("toa alta", "Toa Alta"), + ("toa baja", "Toa Baja"), + ("trujillo alto", "Trujillo Alto"), + ("utuado", "Utuado"), + ("vega alta", "Vega Alta"), + ("vega baja", "Vega Baja"), + ("vieques", "Vieques"), + ("villalba", "Villalba"), + ("yabucoa", "Yabucoa"), + ("yauco", "Yauco"), + ], + max_length=255, + ), ), ] diff --git a/suministrospr/suministros/migrations/0004_suministro_slug.py b/suministrospr/suministros/migrations/0004_suministro_slug.py index 774bdef..285f8bc 100644 --- a/suministrospr/suministros/migrations/0004_suministro_slug.py +++ b/suministrospr/suministros/migrations/0004_suministro_slug.py @@ -1,19 +1,21 @@ # Generated by Django 2.2.9 on 2020-01-14 00:26 -from django.db import migrations import django_extensions.db.fields +from django.db import migrations class Migration(migrations.Migration): dependencies = [ - ('suministros', '0003_auto_20200113_2325'), + ("suministros", "0003_auto_20200113_2325"), ] operations = [ migrations.AddField( - model_name='suministro', - name='slug', - field=django_extensions.db.fields.AutoSlugField(blank=True, editable=False, populate_from=['title', 'municipality']), + model_name="suministro", + name="slug", + field=django_extensions.db.fields.AutoSlugField( + blank=True, editable=False, populate_from=["title", "municipality"] + ), ), ] diff --git a/suministrospr/suministros/models.py b/suministrospr/suministros/models.py index 2ba4883..0fa6573 100644 --- a/suministrospr/suministros/models.py +++ b/suministrospr/suministros/models.py @@ -1,11 +1,10 @@ -from django.db import models -from django.core.cache import cache - from ckeditor.fields import RichTextField +from django.core.cache import cache +from django.db import models from django_extensions.db.fields import AutoSlugField -from .constants import MUNICIPALITIES from ..utils.models import BaseModel +from .constants import MUNICIPALITIES class Suministro(BaseModel): @@ -24,8 +23,10 @@ def save(self, *args, **kwargs): self.invalidate_cache() def invalidate_cache(self): - cache.delete_many([ - "suministro-list", - f"suministro-municipio-list:{self.municipality}", - f"suministro-detail:{self.slug}" - ]) + cache.delete_many( + [ + "suministro-list", + f"suministro-municipio-list:{self.municipality}", + f"suministro-detail:{self.slug}", + ] + ) diff --git a/suministrospr/suministros/urls.py b/suministrospr/suministros/urls.py index 0e63bf9..4c71591 100644 --- a/suministrospr/suministros/urls.py +++ b/suministrospr/suministros/urls.py @@ -1,11 +1,11 @@ from django.urls import path from .views import ( + SuministroByMunicipalityList, SuministroCreate, SuministroDetail, - SuministroUpdate, SuministroList, - SuministroByMunicipalityList, + SuministroUpdate, ) urlpatterns = [ diff --git a/suministrospr/suministros/views.py b/suministrospr/suministros/views.py index 11df83f..2c66c8d 100644 --- a/suministrospr/suministros/views.py +++ b/suministrospr/suministros/views.py @@ -1,11 +1,11 @@ from django.urls import reverse -from django.views.generic import ListView, DetailView +from django.views.generic import DetailView, ListView from django.views.generic.edit import CreateView, UpdateView +from ..utils.mixins import CacheMixin from .constants import MUNICIPALITIES -from .models import Suministro from .forms import SuministroModelForm -from ..utils.mixins import CacheMixin +from .models import Suministro class SuministroList(CacheMixin, ListView): diff --git a/suministrospr/urls.py b/suministrospr/urls.py index ab3797a..dcfd6e6 100644 --- a/suministrospr/urls.py +++ b/suministrospr/urls.py @@ -12,4 +12,3 @@ import debug_toolbar urlpatterns = [path("__debug__/", include(debug_toolbar.urls)),] + urlpatterns - diff --git a/suministrospr/users/admin.py b/suministrospr/users/admin.py index f91be8f..6d53b53 100644 --- a/suministrospr/users/admin.py +++ b/suministrospr/users/admin.py @@ -1,5 +1,6 @@ from django.contrib import admin from django.contrib.auth.admin import UserAdmin + from .models import User admin.site.register(User, UserAdmin) diff --git a/suministrospr/users/migrations/0001_initial.py b/suministrospr/users/migrations/0001_initial.py index 487a52b..ff29f21 100644 --- a/suministrospr/users/migrations/0001_initial.py +++ b/suministrospr/users/migrations/0001_initial.py @@ -4,8 +4,8 @@ import django.contrib.auth.models import django.contrib.auth.validators -from django.db import migrations, models import django.utils.timezone +from django.db import migrations, models class Migration(migrations.Migration): @@ -13,34 +13,120 @@ class Migration(migrations.Migration): initial = True dependencies = [ - ('auth', '0008_alter_user_username_max_length'), + ("auth", "0008_alter_user_username_max_length"), ] operations = [ migrations.CreateModel( - name='User', + name="User", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('password', models.CharField(max_length=128, verbose_name='password')), - ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')), - ('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')), - ('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')), - ('first_name', models.CharField(blank=True, max_length=30, verbose_name='first name')), - ('last_name', models.CharField(blank=True, max_length=30, verbose_name='last name')), - ('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')), - ('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.Group', verbose_name='groups')), - ('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions')), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("password", models.CharField(max_length=128, verbose_name="password")), + ( + "last_login", + models.DateTimeField( + blank=True, null=True, verbose_name="last login" + ), + ), + ( + "is_superuser", + models.BooleanField( + default=False, + help_text="Designates that this user has all permissions without explicitly assigning them.", + verbose_name="superuser status", + ), + ), + ( + "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", + ), + ), + ( + "first_name", + models.CharField( + blank=True, max_length=30, verbose_name="first name" + ), + ), + ( + "last_name", + models.CharField( + blank=True, max_length=30, verbose_name="last name" + ), + ), + ( + "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" + ), + ), + ( + "groups", + models.ManyToManyField( + blank=True, + help_text="The groups this user belongs to. A user will get all permissions granted to each of their groups.", + related_name="user_set", + related_query_name="user", + to="auth.Group", + verbose_name="groups", + ), + ), + ( + "user_permissions", + models.ManyToManyField( + blank=True, + help_text="Specific permissions for this user.", + related_name="user_set", + related_query_name="user", + to="auth.Permission", + verbose_name="user permissions", + ), + ), ], options={ - 'verbose_name_plural': 'users', - 'verbose_name': 'user', - 'abstract': False, + "verbose_name_plural": "users", + "verbose_name": "user", + "abstract": False, }, - managers=[ - ('objects', django.contrib.auth.models.UserManager()), - ], + managers=[("objects", django.contrib.auth.models.UserManager()),], ), ] diff --git a/suministrospr/users/migrations/0002_auto_20200113_2208.py b/suministrospr/users/migrations/0002_auto_20200113_2208.py index 8ce9ba1..0dfaac9 100644 --- a/suministrospr/users/migrations/0002_auto_20200113_2208.py +++ b/suministrospr/users/migrations/0002_auto_20200113_2208.py @@ -6,13 +6,15 @@ class Migration(migrations.Migration): dependencies = [ - ('users', '0001_initial'), + ("users", "0001_initial"), ] operations = [ migrations.AlterField( - model_name='user', - name='last_name', - field=models.CharField(blank=True, max_length=150, verbose_name='last name'), + model_name="user", + name="last_name", + field=models.CharField( + blank=True, max_length=150, verbose_name="last name" + ), ), ] diff --git a/suministrospr/utils/mixins.py b/suministrospr/utils/mixins.py index 684cca6..8b893ce 100644 --- a/suministrospr/utils/mixins.py +++ b/suministrospr/utils/mixins.py @@ -1,5 +1,5 @@ -from django.core.cache import cache from django.conf import settings +from django.core.cache import cache class CacheMixin: diff --git a/suministrospr/wsgi.py b/suministrospr/wsgi.py index 8ace9a6..b08907b 100644 --- a/suministrospr/wsgi.py +++ b/suministrospr/wsgi.py @@ -6,11 +6,11 @@ """ import os +from configurations.wsgi import get_wsgi_application -configuration = os.getenv('ENVIRONMENT', 'development').title() -os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'suministrospr.settings') -os.environ.setdefault('DJANGO_CONFIGURATION', configuration) +configuration = os.getenv("ENVIRONMENT", "development").title() +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "suministrospr.settings") +os.environ.setdefault("DJANGO_CONFIGURATION", configuration) -from configurations.wsgi import get_wsgi_application application = get_wsgi_application()