diff --git a/.coveragerc b/.coveragerc deleted file mode 100644 index 3334c71..0000000 --- a/.coveragerc +++ /dev/null @@ -1,4 +0,0 @@ -[run] -relative_files = True -omit = admin_confirm/tests/* -branch = True diff --git a/.env b/.env new file mode 100644 index 0000000..5802fdc --- /dev/null +++ b/.env @@ -0,0 +1,2 @@ +PYTHON_VERSION=3.8 +DJANGO_VERSION=3.1.7 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3b1ee26..d4fbd19 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -14,47 +14,41 @@ on: - created jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: wemake-python-styleguide + uses: wemake-services/wemake-python-styleguide@0.15.2 + with: + path: admin_confirm + reporter: 'github-pr-review' + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + continue-on-error: true + test: runs-on: ubuntu-latest strategy: matrix: python-version: [3.6, 3.7, 3.8, 3.9] django-version: [2.2, 3.0] + env: + DJANGO_VERSION: ${{ matrix.django-version }} + PYTHON_VERSION: ${{ matrix.python-version }} + COMPOSE_INTERACTIVE_NO_CLI: 1 steps: - uses: actions/checkout@v2 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 - with: - python-version: ${{ matrix.python-version }} - - name: Install Django ${{ matrix.django-version }} + - name: Build Docker for Python 3.6 + if: ${{ matrix.python-version == 3.6 }} run: | - pip install django==${{ matrix.django-version }} - - name: Install dependencies + export SELENIUM_VERSION=3.141.0 + docker-compose build + - name: Build Docker for other Python versions + if: ${{ matrix.python-version != 3.6 }} run: | - python -m pip install --upgrade pip - pip install flake8 pytest - if [ -f requirements.txt ]; then pip install -r requirements.txt; fi - - name: Lint with flake8 - run: | - # stop the build if there are Python syntax errors or undefined names - flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics - # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide - flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics - - name: Unit Test - run: | - make test - - name: Coveralls - uses: AndreMiras/coveralls-python-action@develop - with: - parallel: true - flag-name: Unit Test - - integration-test: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Build Docker - run: docker-compose build + export SELENIUM_VERSION=4.0.0a7 + docker-compose build - name: Start Docker run: docker-compose up -d - name: Integration Test @@ -63,10 +57,9 @@ jobs: uses: AndreMiras/coveralls-python-action@develop with: parallel: true - flag-name: Integration Test coveralls: - needs: [test, integration-test] + needs: [test] runs-on: ubuntu-latest steps: - name: Coveralls Finished diff --git a/Dockerfile b/Dockerfile index d388347..f06a924 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,12 @@ -FROM python:3 +ARG PYTHON_VERSION=3.8 +FROM python:${PYTHON_VERSION} ENV PYTHONUNBUFFERED=1 ENV USE_DOCKER=true WORKDIR /code -COPY requirements.txt /code/ -RUN pip install -r requirements.txt COPY . /code/ +ARG DJANGO_VERSION="3.1.7" +RUN pip install django==${DJANGO_VERSION} +RUN pip install -r requirements.txt +RUN pip install -e . +ARG SELENIUM_VERSION="4.0.0a7" +RUN pip install selenium~=${SELENIUM_VERSION} diff --git a/README.md b/README.md index 7aa1232..5ae4eb3 100644 --- a/README.md +++ b/README.md @@ -153,6 +153,13 @@ pyenv vituralenv 3.8.0 django-admin-confirm-3.8.0 Now your terminal should have `(django-admin-confirm-3.8.0)` prefix, because `.python-version` should have auto switch your virtual env +Install requirements + +``` +pip install -r requirements.txt +pip install -e . +``` + Run **migrations** and create a superuser and run the server ``` @@ -237,7 +244,6 @@ pip uninstall django_admin_confirm make install-testpypi VERSION= ``` -Update version in `requirements.txt` Add test locally ``` diff --git a/admin_confirm/admin.py b/admin_confirm/admin.py index 9286bec..615de0e 100644 --- a/admin_confirm/admin.py +++ b/admin_confirm/admin.py @@ -11,7 +11,6 @@ from django.forms import ModelForm from admin_confirm.utils import get_admin_change_url, snake_to_title_case from django.core.cache import cache from django.views.decorators.cache import cache_control -from django.forms.formsets import all_valid from admin_confirm.constants import ( CACHE_TIMEOUT, CONFIRMATION_RECEIVED, @@ -139,7 +138,7 @@ class AdminConfirmMixin: return [initial_value, new_value] if initial_value: - if new_value == False: + if new_value is False: # Clear has been selected return [initial_value.name, None] elif new_value: @@ -249,7 +248,7 @@ class AdminConfirmMixin: if CONFIRM_CHANGE in modified_post: del modified_post[CONFIRM_CHANGE] - if object_id and not SAVE_AS_NEW in request.POST: + if object_id and SAVE_AS_NEW not in request.POST: # Update the obj with the new uploaded files # then pass rest of changes to Django obj = self.model.objects.filter(id=object_id).first() @@ -287,6 +286,20 @@ class AdminConfirmMixin: cache.delete_many(CACHE_KEYS.values()) return super()._changeform_view(request, object_id, form_url, extra_context) + def _get_cleared_fields(self, request): + """ + Checks for any ImageField or FileField which have been cleared by user. + + Because the form that is generated by Django for the model, would not have the + `-clear` inputs in them, they have to be injected into the hidden form + on the confirmation page. + """ + return [ + input_name.split("-clear")[0] + for input_name in request.POST.keys() + if input_name.endswith("-clear") + ] + def _change_confirmation_view(self, request, object_id, form_url, extra_context): # This code is taken from super()._changeform_view # https://github.com/django/django/blob/master/django/contrib/admin/options.py#L1575-L1592 @@ -348,10 +361,14 @@ class AdminConfirmMixin: save_action = key break + cleared_fields = [] if form.is_multipart(): cache.set(CACHE_KEYS["post"], request.POST, timeout=CACHE_TIMEOUT) cache.set(CACHE_KEYS["object"], new_object, timeout=CACHE_TIMEOUT) + # Handle when files are cleared - since the `form` object would not hold that info + cleared_fields = self._get_cleared_fields(request) + title_action = _("adding") if add_or_new else _("changing") context = { **self.admin_site.each_context(request), @@ -368,6 +385,7 @@ class AdminConfirmMixin: "save_as_new": SAVE_AS_NEW in request.POST, "submit_name": save_action, "form": form, + "cleared_fields": cleared_fields, "formsets": formsets, **(extra_context or {}), } diff --git a/admin_confirm/templates/admin/change_confirmation.html b/admin_confirm/templates/admin/change_confirmation.html index 433c75d..ff21a0b 100644 --- a/admin_confirm/templates/admin/change_confirmation.html +++ b/admin_confirm/templates/admin/change_confirmation.html @@ -40,8 +40,11 @@ {% include "admin/change_data.html" %}
{% csrf_token %} -