Setting up pyenv and show default value on confirm add (#7)
Co-authored-by: Thu Trang Pham <thu@joinmodernhealth.com>main
parent
591aa48ba0
commit
209de62c9d
|
|
@ -0,0 +1 @@
|
|||
django-admin-confirm-3.8
|
||||
1
Makefile
1
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
|
||||
|
|
|
|||
34
README.md
34
README.md
|
|
@ -6,6 +6,8 @@ AdminConfirmMixin is a mixin for ModelAdmin to add confirmations to change, add
|
|||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
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.
|
||||
|
|
|
|||
|
|
@ -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():
|
||||
|
|
|
|||
|
|
@ -1,11 +1,19 @@
|
|||
{% if changed_data %}
|
||||
<div class="changed-data">
|
||||
<div class="changed-data">
|
||||
<p><b>Confirm Values:</b></p>
|
||||
<table>
|
||||
<tr><th>Field</th><th>Current Value</th><th>New Value</th></tr>
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>{% if add %} Default {% else %} Current {% endif %}Value</th>
|
||||
<th>New Value</th>
|
||||
</tr>
|
||||
{% for field, values in changed_data.items %}
|
||||
<tr><td>{{ field }}</td><td>{{ values.0 }}</td><td>{{ values.1 }}</td></tr>
|
||||
<tr>
|
||||
<td>{{ field }}</td>
|
||||
<td>{{ values.0 }}</td>
|
||||
<td>{{ values.1 }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
|
|
|||
|
|
@ -9,13 +9,13 @@
|
|||
</mask>
|
||||
<g mask="url(#a)">
|
||||
<path fill="#555" d="M0 0h63v20H0z"/>
|
||||
<path fill="#4c1" d="M63 0h36v20H63z"/>
|
||||
<path fill="#fe7d37" d="M63 0h36v20H63z"/>
|
||||
<path fill="url(#b)" d="M0 0h99v20H0z"/>
|
||||
</g>
|
||||
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
|
||||
<text x="31.5" y="15" fill="#010101" fill-opacity=".3">coverage</text>
|
||||
<text x="31.5" y="14">coverage</text>
|
||||
<text x="80" y="15" fill="#010101" fill-opacity=".3">100%</text>
|
||||
<text x="80" y="14">100%</text>
|
||||
<text x="80" y="15" fill="#010101" fill-opacity=".3">42%</text>
|
||||
<text x="80" y="14">42%</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 903 B After Width: | Height: | Size: 904 B |
|
|
@ -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
|
||||
|
|
@ -1,2 +1,10 @@
|
|||
Django>=1.7.0
|
||||
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
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 33 KiB |
1
setup.py
1
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,
|
||||
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
),
|
||||
]
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
from .local import *
|
||||
|
|
@ -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/"
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
from .base import *
|
||||
|
||||
INSTALLED_APPS = INSTALLED_APPS + ['market']
|
||||
WSGI_APPLICATION = "test_project.wsgi.application"
|
||||
ROOT_URLCONF = "test_project.urls"
|
||||
|
|
@ -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"
|
||||
Loading…
Reference in New Issue