From 209de62c9d50e4e592726b7ab4d8dc12fd11a5a5 Mon Sep 17 00:00:00 2001 From: Thu Trang Pham Date: Tue, 9 Feb 2021 17:03:18 -0800 Subject: [PATCH] Setting up pyenv and show default value on confirm add (#7) Co-authored-by: Thu Trang Pham --- .python-version | 1 + Makefile | 1 - README.md | 34 ++++++ admin_confirm/admin.py | 8 +- .../templates/admin/change_data.html | 26 ++-- coverage.svg | 6 +- pytest.ini | 4 +- requirements.txt | 10 +- screenshot_confirm_add.png | Bin 0 -> 33950 bytes setup.py | 1 - .../market/migrations/0004_inventory_notes.py | 18 +++ tests/market/models.py | 1 + tests/test_project/settings.py | 6 +- tests/test_project/settings/__init__.py | 1 + tests/test_project/settings/base.py | 115 ++++++++++++++++++ tests/test_project/settings/local.py | 5 + tests/test_project/settings/test.py | 5 + 17 files changed, 219 insertions(+), 23 deletions(-) create mode 100644 .python-version create mode 100644 screenshot_confirm_add.png create mode 100644 tests/market/migrations/0004_inventory_notes.py create mode 100644 tests/test_project/settings/__init__.py create mode 100644 tests/test_project/settings/base.py create mode 100644 tests/test_project/settings/local.py create mode 100644 tests/test_project/settings/test.py diff --git a/.python-version b/.python-version new file mode 100644 index 0000000..f29ad5b --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +django-admin-confirm-3.8 diff --git a/Makefile b/Makefile index 9aa3455..8136d45 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,6 @@ test: coverage run --branch -m pytest coverage html coverage-badge -f -o coverage.svg - python -m readme_renderer README.md -o /tmp/README.html check-readme: python -m readme_renderer README.md -o /tmp/README.html diff --git a/README.md b/README.md index 8b141ce..c51059d 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,8 @@ AdminConfirmMixin is a mixin for ModelAdmin to add confirmations to change, add ![Screenshot of Change Confirmation Page](https://raw.githubusercontent.com/TrangPham/django-admin-confirm/32192d3988a9bd44c734a66baff91f02dd28136b/screenshot.png) +![Screenshot of Add Confirmation Page](https://raw.githubusercontent.com/TrangPham/django-admin-confirm/32192d3988a9bd44c734a66baff91f02dd28136b/screenshot_confirm_add.png) + ![Screenshot of Action Confirmation Page](https://raw.githubusercontent.com/TrangPham/django-admin-confirm/264900a21658cc979dd2026038db73f8a1b73c64/screenshot_confirm_action.png) It can be configured to add a confirmation page on ModelAdmin upon: @@ -126,6 +128,38 @@ Your appreciation is also very welcome :) Feel free to: - star the project - open an issue just to share your thanks +### Local Development Setup + +Install pyenv +Install python 3.8 + +Create virtualenv via pyenv + +``` +pyenv vituralenv 3.8 django-admin-confirm-3.8 +``` + +Now your terminal should have `(django-admin-confirm-3.8)` prefix, because `.python-version` should have auto switch your virtual env + +Run migrations and create a superuser and run the server + +``` +./tests/manage.py migrate +./tests/manage.py createsuperuser +./tests/manage.py runserver +``` + +You should be able to see the test app at `localhost:8000/admin` + +Running tests: + +``` +make test +tox +``` + +Testing new changes on test project: + ## Feature List This is a list of features which could potentially be added in the future. Some of which might make more sense in their own package. diff --git a/admin_confirm/admin.py b/admin_confirm/admin.py index 83f0bef..f5f0e61 100644 --- a/admin_confirm/admin.py +++ b/admin_confirm/admin.py @@ -134,14 +134,16 @@ class AdminConfirmMixin: changed_data = {} if form_validated: if add: - for name in form.changed_data: + for name in form.cleaned_data: new_value = getattr(new_object, name) # Don't consider default values as changed for adding + default_value = model._meta.get_field(name).get_default() if ( new_value is not None - and new_value != model._meta.get_field(name).default + and new_value != default_value ): - changed_data[name] = [None, new_value] + # Show what the default value is + changed_data[name] = [str(default_value), new_value] else: # Parse the changed data - Note that using form.changed_data would not work because initial is not set for name, field in form.fields.items(): diff --git a/admin_confirm/templates/admin/change_data.html b/admin_confirm/templates/admin/change_data.html index 713f835..efd4b73 100644 --- a/admin_confirm/templates/admin/change_data.html +++ b/admin_confirm/templates/admin/change_data.html @@ -1,11 +1,19 @@ {% if changed_data %} -
-

Confirm Values:

- - - {% for field, values in changed_data.items %} - - {% endfor %} -
FieldCurrent ValueNew Value
{{ field }}{{ values.0 }}{{ values.1 }}
-
+
+

Confirm Values:

+ + + + + + + {% for field, values in changed_data.items %} + + + + + + {% endfor %} +
Field{% if add %} Default {% else %} Current {% endif %}ValueNew Value
{{ field }}{{ values.0 }}{{ values.1 }}
+
{% endif %} diff --git a/coverage.svg b/coverage.svg index e5db27c..5cc1bb5 100644 --- a/coverage.svg +++ b/coverage.svg @@ -9,13 +9,13 @@ - + coverage coverage - 100% - 100% + 42% + 42% diff --git a/pytest.ini b/pytest.ini index 228da49..729510f 100644 --- a/pytest.ini +++ b/pytest.ini @@ -1,4 +1,4 @@ [pytest] -DJANGO_SETTINGS_MODULE=tests.test_project.settings +DJANGO_SETTINGS_MODULE=tests.test_project.settings.test addopts = --doctest-modules -ra -l --tb=short --show-capture=log --color=yes -testpaths = admin_confirm \ No newline at end of file +testpaths = admin_confirm diff --git a/requirements.txt b/requirements.txt index 9fa7e6a..48ea57d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,10 @@ Django>=1.7.0 -factory-boy~=3.0.1 \ No newline at end of file +factory-boy~=3.0.1 +django-admin-confirm~=0.2.1 +coverage~=5.4 +pytest~=6.2.2 +tox~=3.21.4 +pytest-django~=4.1.0 +coverage-badge~=1.0.1 +readme-renderer~=28.0 +twine~=3.3.0 diff --git a/screenshot_confirm_add.png b/screenshot_confirm_add.png new file mode 100644 index 0000000000000000000000000000000000000000..4373e12057f4cef09b683dbf1069c6c929f1944e GIT binary patch literal 33950 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 aO4J?rqa3cZQi2CLBm4O2qdX}C-~RzAc6tN= literal 0 HcmV?d00001 diff --git a/setup.py b/setup.py index 9c95ef2..300be52 100644 --- a/setup.py +++ b/setup.py @@ -25,5 +25,4 @@ setup( # ISSUE-4: Ensure that package includes template and css folders # list files in MANIFEST.in include_package_data=True, - ) diff --git a/tests/market/migrations/0004_inventory_notes.py b/tests/market/migrations/0004_inventory_notes.py new file mode 100644 index 0000000..ab483c2 --- /dev/null +++ b/tests/market/migrations/0004_inventory_notes.py @@ -0,0 +1,18 @@ +# Generated by Django 3.1.6 on 2021-02-10 00:01 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('market', '0003_auto_20201108_1717'), + ] + + operations = [ + migrations.AddField( + model_name='inventory', + name='notes', + field=models.TextField(blank=True, default='This is the default', null=True), + ), + ] diff --git a/tests/market/models.py b/tests/market/models.py index 8b8a0bd..3ba1436 100644 --- a/tests/market/models.py +++ b/tests/market/models.py @@ -32,3 +32,4 @@ class Inventory(models.Model): ) item = models.ForeignKey(to=Item, on_delete=models.CASCADE) quantity = models.PositiveIntegerField(default=0, null=True, blank=True) + notes = models.TextField(default="This is the default", null=True, blank=True) diff --git a/tests/test_project/settings.py b/tests/test_project/settings.py index 7ce07ab..ed390d3 100644 --- a/tests/test_project/settings.py +++ b/tests/test_project/settings.py @@ -37,7 +37,7 @@ INSTALLED_APPS = [ "django.contrib.sessions", "django.contrib.messages", "django.contrib.staticfiles", - "tests.market", + "market", ] MIDDLEWARE = [ @@ -50,7 +50,7 @@ MIDDLEWARE = [ "django.middleware.clickjacking.XFrameOptionsMiddleware", ] -ROOT_URLCONF = "tests.test_project.urls" +ROOT_URLCONF = "test_project.urls" TEMPLATES = [ { @@ -68,7 +68,7 @@ TEMPLATES = [ }, ] -WSGI_APPLICATION = "tests.test_project.wsgi.application" +WSGI_APPLICATION = "test_project.wsgi.application" # Database diff --git a/tests/test_project/settings/__init__.py b/tests/test_project/settings/__init__.py new file mode 100644 index 0000000..8f607e4 --- /dev/null +++ b/tests/test_project/settings/__init__.py @@ -0,0 +1 @@ +from .local import * diff --git a/tests/test_project/settings/base.py b/tests/test_project/settings/base.py new file mode 100644 index 0000000..4cff103 --- /dev/null +++ b/tests/test_project/settings/base.py @@ -0,0 +1,115 @@ +""" +Django settings for test_project project. + +Generated by 'django-admin startproject' using Django 3.0.10. + +For more information on this file, see +https://docs.djangoproject.com/en/3.0/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/3.0/ref/settings/ +""" + +import os + +# Build paths inside the project like this: os.path.join(BASE_DIR, ...) +BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/3.0/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = "=yddl-40388w3e2hl$e8)revce=n67_idi8pfejtn3!+2%!_qt" + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = True + +ALLOWED_HOSTS = ["127.0.0.1", "localhost"] + + +# Application definition + +INSTALLED_APPS = [ + "admin_confirm", + "django.contrib.admin", + "django.contrib.auth", + "django.contrib.contenttypes", + "django.contrib.sessions", + "django.contrib.messages", + "django.contrib.staticfiles", +] + +MIDDLEWARE = [ + "django.middleware.security.SecurityMiddleware", + "django.contrib.sessions.middleware.SessionMiddleware", + "django.middleware.common.CommonMiddleware", + "django.middleware.csrf.CsrfViewMiddleware", + "django.contrib.auth.middleware.AuthenticationMiddleware", + "django.contrib.messages.middleware.MessageMiddleware", + "django.middleware.clickjacking.XFrameOptionsMiddleware", +] + +TEMPLATES = [ + { + "BACKEND": "django.template.backends.django.DjangoTemplates", + "DIRS": [], + "APP_DIRS": True, + "OPTIONS": { + "context_processors": [ + "django.template.context_processors.debug", + "django.template.context_processors.request", + "django.contrib.auth.context_processors.auth", + "django.contrib.messages.context_processors.messages", + ], + }, + }, +] + +# Database +# https://docs.djangoproject.com/en/3.0/ref/settings/#databases + +DATABASES = { + "default": { + "ENGINE": "django.db.backends.sqlite3", + "NAME": os.path.join(BASE_DIR, "db.sqlite3"), + } +} + + +# Password validation +# https://docs.djangoproject.com/en/3.0/ref/settings/#auth-password-validators + +AUTH_PASSWORD_VALIDATORS = [ + { + "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator", + }, + { + "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator", + }, + { + "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator", + }, + { + "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator", + }, +] + + +# Internationalization +# https://docs.djangoproject.com/en/3.0/topics/i18n/ + +LANGUAGE_CODE = "en-us" + +TIME_ZONE = "UTC" + +USE_I18N = True + +USE_L10N = True + +USE_TZ = True + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/3.0/howto/static-files/ + +STATIC_URL = "/static/" diff --git a/tests/test_project/settings/local.py b/tests/test_project/settings/local.py new file mode 100644 index 0000000..80a24fc --- /dev/null +++ b/tests/test_project/settings/local.py @@ -0,0 +1,5 @@ +from .base import * + +INSTALLED_APPS = INSTALLED_APPS + ['market'] +WSGI_APPLICATION = "test_project.wsgi.application" +ROOT_URLCONF = "test_project.urls" diff --git a/tests/test_project/settings/test.py b/tests/test_project/settings/test.py new file mode 100644 index 0000000..2e221c3 --- /dev/null +++ b/tests/test_project/settings/test.py @@ -0,0 +1,5 @@ +from .base import * + +INSTALLED_APPS = INSTALLED_APPS + ['tests.market'] +WSGI_APPLICATION = "tests.test_project.wsgi.application" +ROOT_URLCONF = "tests.test_project.urls"