Refactored and added pytest.ini file
parent
3c47e66ca1
commit
a63d4292b1
|
|
@ -13,7 +13,10 @@ class AdminConfirmMixin(object):
|
||||||
# Should we ask for confirmation for changes?
|
# Should we ask for confirmation for changes?
|
||||||
confirm_change = None
|
confirm_change = None
|
||||||
|
|
||||||
# if confirm_change, which fields should we confirm for?
|
# Should we ask for confirmation for additions?
|
||||||
|
confirm_add = None
|
||||||
|
|
||||||
|
# If asking for confirmation, which fields should we confirm for?
|
||||||
confirmation_fields = None
|
confirmation_fields = None
|
||||||
|
|
||||||
# Custom templates (designed to be over-ridden in subclasses)
|
# Custom templates (designed to be over-ridden in subclasses)
|
||||||
|
|
@ -50,20 +53,20 @@ class AdminConfirmMixin(object):
|
||||||
context,
|
context,
|
||||||
)
|
)
|
||||||
|
|
||||||
def change_view(self, request, object_id=None, form_url="", extra_context=None):
|
def changeform_view(self, request, object_id=None, form_url="", extra_context=None):
|
||||||
if request.method == "POST" and request.POST.get("_confirm_change"):
|
if request.method == "POST":
|
||||||
return self._change_confirmation_view(
|
if (not object_id and "_confirm_add" in request.POST) or (object_id and "_confirm_change"):
|
||||||
request, object_id, form_url, extra_context
|
return self._change_confirmation_view(request, object_id, form_url, extra_context)
|
||||||
)
|
|
||||||
|
|
||||||
extra_context = {
|
extra_context = {
|
||||||
**(extra_context or {}),
|
**(extra_context or {}),
|
||||||
|
'confirm_add': self.confirm_add,
|
||||||
'confirm_change': self.confirm_change
|
'confirm_change': self.confirm_change
|
||||||
}
|
}
|
||||||
return super().change_view(request, object_id, form_url, extra_context)
|
return super().changeform_view(request, object_id, form_url, extra_context)
|
||||||
|
|
||||||
def _change_confirmation_view(self, request, object_id, form_url, extra_context):
|
def _change_confirmation_view(self, request, object_id, form_url, extra_context):
|
||||||
# This code is taken from __changeform_view
|
# This code is taken from super()._changeform_view
|
||||||
to_field = request.POST.get(
|
to_field = request.POST.get(
|
||||||
TO_FIELD_VAR, request.GET.get(TO_FIELD_VAR)
|
TO_FIELD_VAR, request.GET.get(TO_FIELD_VAR)
|
||||||
)
|
)
|
||||||
|
|
@ -76,7 +79,13 @@ class AdminConfirmMixin(object):
|
||||||
opts = model._meta
|
opts = model._meta
|
||||||
|
|
||||||
add = object_id is None
|
add = object_id is None
|
||||||
|
if add:
|
||||||
|
if not self.has_add_permission(request):
|
||||||
|
raise PermissionDenied
|
||||||
|
|
||||||
|
obj = None
|
||||||
|
else:
|
||||||
|
self.message_user(request, add)
|
||||||
obj = self.get_object(request, unquote(object_id), to_field)
|
obj = self.get_object(request, unquote(object_id), to_field)
|
||||||
|
|
||||||
if obj is None:
|
if obj is None:
|
||||||
|
|
@ -97,17 +106,23 @@ class AdminConfirmMixin(object):
|
||||||
else:
|
else:
|
||||||
new_object = form.instance
|
new_object = form.instance
|
||||||
|
|
||||||
# Parse the changed data - Note that using form.changed_data would not work as initial is not set
|
|
||||||
changed_data = {}
|
changed_data = {}
|
||||||
|
if add:
|
||||||
|
for name in form.changed_data:
|
||||||
|
changed_data[name] = [None, new_object.__getattribute__(name)]
|
||||||
|
else:
|
||||||
|
# Parse the changed data - Note that using form.changed_data would not work as initial is not set
|
||||||
for name, field in form.fields.items():
|
for name, field in form.fields.items():
|
||||||
initial_value = obj.__getattribute__(name)
|
initial_value = obj.__getattribute__(name)
|
||||||
new_value = new_object.__getattribute__(name)
|
new_value = new_object.__getattribute__(name)
|
||||||
if field.has_changed(initial_value, new_value) and initial_value != new_value:
|
if field.has_changed(initial_value, new_value) and initial_value != new_value:
|
||||||
changed_data[name] = [initial_value, new_value]
|
changed_data[name] = [initial_value, new_value]
|
||||||
|
|
||||||
if not bool(set(self.get_confirmation_fields(request, obj)) & set(changed_data.keys())):
|
changed_confirmation_fields = set(self.get_confirmation_fields(request, obj)) & set(changed_data.keys())
|
||||||
|
self.message_user(request, changed_confirmation_fields)
|
||||||
|
if not bool(changed_confirmation_fields):
|
||||||
# No confirmation required for changed fields, continue to save
|
# No confirmation required for changed fields, continue to save
|
||||||
return super().change_view(request, object_id, form_url, extra_context)
|
return super()._changeform_view(request, object_id, form_url, extra_context)
|
||||||
|
|
||||||
# Parse the original save action from request
|
# Parse the original save action from request
|
||||||
save_action = None
|
save_action = None
|
||||||
|
|
@ -140,6 +155,7 @@ class AdminConfirmMixin(object):
|
||||||
"opts": opts,
|
"opts": opts,
|
||||||
"form_data": form_data,
|
"form_data": form_data,
|
||||||
"changed_data": changed_data,
|
"changed_data": changed_data,
|
||||||
|
"add": add,
|
||||||
"submit_name": save_action,
|
"submit_name": save_action,
|
||||||
**(extra_context or {}),
|
**(extra_context or {}),
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,17 +19,35 @@
|
||||||
<div class="breadcrumbs">
|
<div class="breadcrumbs">
|
||||||
<a href="{% url 'admin:index' %}">{% trans 'Home' %}</a>
|
<a href="{% url 'admin:index' %}">{% trans 'Home' %}</a>
|
||||||
› <a href="{% url 'admin:app_list' app_label=opts.app_label %}">{{ opts.app_config.verbose_name }}</a>
|
› <a href="{% url 'admin:app_list' app_label=opts.app_label %}">{{ opts.app_config.verbose_name }}</a>
|
||||||
› <a href="{% url opts|admin_urlname:'changelist' %}">{{ opts.verbose_name_plural|capfirst }}</a>
|
{% if not add %}
|
||||||
› <a href="{% url opts|admin_urlname:'change' object_id|admin_urlquote %}">{{ object_name|truncatewords:"18" }}</a>
|
› <a href="{% url opts|admin_urlname:'changelist' %}">{{ opts.verbose_name_plural|capfirst }}</a>
|
||||||
› {% trans 'Change Confirmation' %}
|
› <a href="{% url opts|admin_urlname:'change' object_id|admin_urlquote %}">{{ object_name|truncatewords:"18" }}</a>
|
||||||
|
› {% trans 'Confirm change' %}
|
||||||
|
{% else %}
|
||||||
|
› {% trans 'Confirm add' %}
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
{% if add %}
|
||||||
|
<p>{% blocktrans with escaped_object=object %}Are you sure you want to add the {{ model_name }}?{% endblocktrans %}</p>
|
||||||
|
{% if changed_data %}
|
||||||
|
<div class="changed-data">
|
||||||
|
<p><b>Confirm Values:</b></p>
|
||||||
|
<table>
|
||||||
|
{% for field, values in changed_data.items %}
|
||||||
|
<tr><th style="text-align: right">{{ field }}:</th><td>{{ values.1 }}</td></tr>
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<form method="post" action="{% url opts|admin_urlname:'add'%}">{% csrf_token %}
|
||||||
|
{% endif %}
|
||||||
|
{% else %}
|
||||||
<p>{% blocktrans with escaped_object=object %}Are you sure you want to change the {{ model_name }} "{{ object_name }}"?{% endblocktrans %}</p>
|
<p>{% blocktrans with escaped_object=object %}Are you sure you want to change the {{ model_name }} "{{ object_name }}"?{% endblocktrans %}</p>
|
||||||
{% if changed_data %}
|
{% if changed_data %}
|
||||||
<div class="changed-data">
|
<div class="changed-data">
|
||||||
<p><b>Detected Changes:</b></p>
|
<p><b>Confirm Values:</b></p>
|
||||||
<table>
|
<table>
|
||||||
<tr><th>Field</th><th>Current Value</th><th>New Value</th></tr>
|
<tr><th>Field</th><th>Current Value</th><th>New Value</th></tr>
|
||||||
{% for field, values in changed_data.items %}
|
{% for field, values in changed_data.items %}
|
||||||
|
|
@ -39,6 +57,7 @@
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<form method="post" action="{% url opts|admin_urlname:'change' object_id|admin_urlquote %}">{% csrf_token %}
|
<form method="post" action="{% url opts|admin_urlname:'change' object_id|admin_urlquote %}">{% csrf_token %}
|
||||||
|
{% endif %}
|
||||||
<div>
|
<div>
|
||||||
{% for key, value in form_data.items %}
|
{% for key, value in form_data.items %}
|
||||||
<input type="hidden" name="{{ key }}" value="{{ value }}">
|
<input type="hidden" name="{{ key }}" value="{{ value }}">
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,10 @@
|
||||||
|
|
||||||
{% block submit-row %}
|
{% block submit-row %}
|
||||||
{% if confirm_change %}
|
{% if confirm_change %}
|
||||||
<input hidden name="_confirm_change" value="{{ confirm_change }}" />
|
<input hidden name="_confirm_change" />
|
||||||
|
{% endif %}
|
||||||
|
{% if confirm_add %}
|
||||||
|
<input hidden name="_confirm_add" />
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{{ block.super }}
|
{{ block.super }}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
[pytest]
|
||||||
|
DJANGO_SETTINGS_MODULE=tests.test_project.settings
|
||||||
|
addopts = --doctest-modules -ra -l --tb=short --show-capture=log --color=yes
|
||||||
|
testpaths = admin_confirm
|
||||||
|
|
@ -5,7 +5,7 @@ import sys
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'testproject.settings')
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'test_project.settings')
|
||||||
try:
|
try:
|
||||||
from django.core.management import execute_from_command_line
|
from django.core.management import execute_from_command_line
|
||||||
except ImportError as exc:
|
except ImportError as exc:
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
"""
|
"""
|
||||||
Django settings for testproject project.
|
Django settings for test_project project.
|
||||||
|
|
||||||
Generated by 'django-admin startproject' using Django 3.0.10.
|
Generated by 'django-admin startproject' using Django 3.0.10.
|
||||||
|
|
||||||
|
|
@ -15,7 +15,6 @@ import os
|
||||||
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
|
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
|
||||||
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||||
|
|
||||||
|
|
||||||
# Quick-start development settings - unsuitable for production
|
# Quick-start development settings - unsuitable for production
|
||||||
# See https://docs.djangoproject.com/en/3.0/howto/deployment/checklist/
|
# See https://docs.djangoproject.com/en/3.0/howto/deployment/checklist/
|
||||||
|
|
||||||
|
|
@ -40,7 +39,7 @@ INSTALLED_APPS = [
|
||||||
'django.contrib.messages',
|
'django.contrib.messages',
|
||||||
'django.contrib.staticfiles',
|
'django.contrib.staticfiles',
|
||||||
|
|
||||||
'market',
|
'tests.market',
|
||||||
]
|
]
|
||||||
|
|
||||||
MIDDLEWARE = [
|
MIDDLEWARE = [
|
||||||
|
|
@ -53,7 +52,7 @@ MIDDLEWARE = [
|
||||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||||
]
|
]
|
||||||
|
|
||||||
ROOT_URLCONF = 'testproject.urls'
|
ROOT_URLCONF = 'tests.test_project.urls'
|
||||||
|
|
||||||
TEMPLATES = [
|
TEMPLATES = [
|
||||||
{
|
{
|
||||||
|
|
@ -71,7 +70,7 @@ TEMPLATES = [
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
WSGI_APPLICATION = 'testproject.wsgi.application'
|
WSGI_APPLICATION = 'tests.test_project.wsgi.application'
|
||||||
|
|
||||||
|
|
||||||
# Database
|
# Database
|
||||||
|
|
@ -2,6 +2,6 @@ import os
|
||||||
|
|
||||||
from django.core.wsgi import get_wsgi_application
|
from django.core.wsgi import get_wsgi_application
|
||||||
|
|
||||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'testproject.settings')
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'test_project.settings')
|
||||||
|
|
||||||
application = get_wsgi_application()
|
application = get_wsgi_application()
|
||||||
Loading…
Reference in New Issue