diff --git a/CHANGES.rst b/CHANGES.rst index 7ee9c56..c6457ac 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,6 +1,11 @@ Changelog ========= +0.1.2 +----- +* Bump up version +* Fix "Select all" issue + 0.1.1 ----- diff --git a/README.rst b/README.rst index 8695763..5b4246d 100644 --- a/README.rst +++ b/README.rst @@ -6,7 +6,7 @@ Django bulk admin enables you to bulk add, bulk edit, bulk upload and bulk selec View the screenshots below to get an idea of how django bulk admin does look like. -Requires Django >= 1.7. +**This is a fork that is ahead of the master as my pull requests are not merged.** Supports Django 3 and 4. Seems to be working with Django 5. =========== diff --git a/bulk_admin/admin.py b/bulk_admin/admin.py index 032e017..a6acd4b 100644 --- a/bulk_admin/admin.py +++ b/bulk_admin/admin.py @@ -5,21 +5,20 @@ from django.contrib import admin, messages from django.contrib.admin.exceptions import DisallowedModelAdminToField from django.contrib.admin.options import IS_POPUP_VAR, InlineModelAdmin, TO_FIELD_VAR, csrf_protect_m -from django.contrib.admin.templatetags.admin_static import static from django.contrib.admin.templatetags.admin_urls import add_preserved_filters from django.contrib.admin.utils import NestedObjects, flatten_fieldsets from django.core.exceptions import PermissionDenied, ValidationError -from django.core.urlresolvers import reverse from django.db import router, transaction from django.forms.formsets import DELETION_FIELD_NAME, INITIAL_FORM_COUNT, TOTAL_FORM_COUNT, ManagementForm from django.forms.models import modelform_defines_fields, modelformset_factory, BaseModelFormSet from django.forms.utils import ErrorList from django.http import HttpResponseRedirect from django.template.response import SimpleTemplateResponse -from django.utils import six -from django.utils.encoding import force_text +from django.urls import reverse +from django.utils.encoding import force_str from django.utils.text import get_text_list -from django.utils.translation import ugettext as _, ugettext_lazy +from django.utils.translation import gettext as _, gettext_lazy +from django.conf.urls.static import static from functools import partial, update_wrapper import django @@ -65,7 +64,7 @@ def __init__(self, *args, **kwargs): ] def get_urls(self): - from django.conf.urls import url + from django.urls import re_path def wrap(view): def wrapper(*args, **kwargs): @@ -75,7 +74,7 @@ def wrapper(*args, **kwargs): info = self.model._meta.app_label, self.model._meta.model_name urlpatterns = super(BulkModelAdmin, self).get_urls() - urlpatterns.insert(0, url(r'^bulk/$', wrap(self.bulk_view), name='%s_%s_bulk' % info)) + urlpatterns.insert(0, re_path(r'^bulk/$', wrap(self.bulk_view), name='%s_%s_bulk' % info)) return urlpatterns @@ -158,7 +157,7 @@ def bulk_view(self, request, form_url='', extra_context=None): formset = formset_class(**formset_params) - msg = _('The %s were bulk added successfully. You may edit them again below.') % (force_text(opts.verbose_name_plural),) + msg = _('The %s were bulk added successfully. You may edit them again below.') % (force_str(opts.verbose_name_plural),) self.message_user(request, msg, messages.SUCCESS) else: @@ -175,23 +174,23 @@ def bulk_view(self, request, form_url='', extra_context=None): if formset.is_bound: errors.extend(formset.non_form_errors()) for formset_errors in formset.errors: - errors.extend(list(six.itervalues(formset_errors))) - - context = dict( - self.admin_site.each_context(request) if django.VERSION >= (1, 8) else self.admin_site.each_context(), - bulk=True, - bulk_formset_prefix=prefix, - bulk_upload_fields=self.get_bulk_upload_fields(request), - title=_('Bulk add %s') % force_text(opts.verbose_name_plural), - is_popup=(IS_POPUP_VAR in request.POST or + errors.extend(list(iter(formset_errors.values()))) + + context = self.admin_site.each_context(request) + context.update({ + 'bulk': True, + 'bulk_formset_prefix': prefix, + 'bulk_upload_fields': self.get_bulk_upload_fields(request), + 'title': _('Bulk add %s') % force_str(opts.verbose_name_plural), + 'is_popup': (IS_POPUP_VAR in request.POST or IS_POPUP_VAR in request.GET), - to_field=to_field, - media=media, - inline_admin_formsets=inline_formsets, - errors=errors, - preserved_filters=self.get_preserved_filters(request), - ) - + 'to_field': to_field, + 'media': media, + 'inline_admin_formsets': inline_formsets, + 'errors': errors, + 'preserved_filters': self.get_preserved_filters(request), + 'adminform': admin.helpers.AdminForm(ManagementForm(), [], {}), + }) context.update(extra_context or {}) return self.render_change_form(request, context, add=True, change=False, obj=None, form_url=form_url) @@ -201,8 +200,8 @@ def response_bulk(self, request, formset): opts = model._meta preserved_filters = self.get_preserved_filters(request) msg_dict = { - 'name': force_text(opts.verbose_name), - 'name_plural': force_text(opts.verbose_name_plural), + 'name': force_str(opts.verbose_name), + 'name_plural': force_str(opts.verbose_name_plural), } if IS_POPUP_VAR in request.POST: @@ -273,7 +272,7 @@ def transform_post_and_files(self, request, prefix): post.update({ '{}-{}-{}'.format(prefix, index, name): value for name, value - in six.iteritems(form_data_for_file) + in iter(form_data_for_file.items()) }) return post, files, force_continue @@ -312,25 +311,25 @@ def get_bulk_upload_fields(self, request): @property def media(self): media = super(BulkModelAdmin, self).media - media.add_js([static('bulk_admin/js/bulk.js')]) + media._js.extend([static('bulk_admin/js/bulk.js')]) return media def select_related_action(self, request, queryset): return self.response_bulk_popup(request, queryset) - select_related_action.short_description = ugettext_lazy('Select') + select_related_action.short_description = gettext_lazy('Select') def bulk_edit_action(self, request, queryset): model = self.model opts = model._meta - selected = request.POST.getlist(admin.ACTION_CHECKBOX_NAME) + selected = queryset.values_list('pk', flat=True) redirect_url = reverse('admin:%s_%s_bulk' % (opts.app_label, opts.model_name), current_app=self.admin_site.name) return HttpResponseRedirect('{}?pks={}'.format(redirect_url, ','.join(selected))) - bulk_edit_action.short_description = ugettext_lazy('Bulk edit') + bulk_edit_action.short_description = gettext_lazy('Bulk edit') class BulkInlineModelAdmin(InlineModelAdmin): diff --git a/bulk_admin/static/bulk_admin/js/bulk.js b/bulk_admin/static/bulk_admin/js/bulk.js index d5de727..d89c325 100644 --- a/bulk_admin/static/bulk_admin/js/bulk.js +++ b/bulk_admin/static/bulk_admin/js/bulk.js @@ -71,6 +71,7 @@ } $totalFormCountInput.attr('value', this.files.length); + $form.appendTo($('body')); $form.submit(); submitted = true; diff --git a/example_project/migrations/0001_initial.py b/example_project/migrations/0001_initial.py new file mode 100644 index 0000000..614b9fa --- /dev/null +++ b/example_project/migrations/0001_initial.py @@ -0,0 +1,32 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11 on 2018-07-24 20:07 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Image', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('title', models.CharField(max_length=255, unique=True)), + ('data', models.FileField(blank=True, null=True, upload_to='')), + ], + ), + migrations.CreateModel( + name='Project', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('title', models.CharField(max_length=255, unique=True)), + ('images', models.ManyToManyField(blank=True, to='example_project.Image')), + ], + ), + ] diff --git a/example_project/migrations/__init__.py b/example_project/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/example_project/settings.py b/example_project/settings.py index f0140d1..c0a2258 100644 --- a/example_project/settings.py +++ b/example_project/settings.py @@ -45,12 +45,11 @@ 'example_project', ) -MIDDLEWARE_CLASSES = ( +MIDDLEWARE = ( 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', - 'django.contrib.auth.middleware.SessionAuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ) diff --git a/example_project/tests.py b/example_project/tests.py index 59c9312..3e14f61 100644 --- a/example_project/tests.py +++ b/example_project/tests.py @@ -3,7 +3,7 @@ from django.test import TestCase from django.contrib.admin.sites import site as admin_site from django.contrib.auth.models import Permission, User -from django.core.urlresolvers import reverse +from django.urls import reverse from django.utils import six from io import BytesIO diff --git a/example_project/urls.py b/example_project/urls.py index 89b573e..bbc511a 100644 --- a/example_project/urls.py +++ b/example_project/urls.py @@ -15,9 +15,9 @@ 1. Add an import: from blog import urls as blog_urls 2. Add a URL to urlpatterns: url(r'^blog/', include(blog_urls)) """ -from django.conf.urls import include, url +from django.conf.urls import url from django.contrib import admin urlpatterns = [ - url(r'^admin/', include(admin.site.urls)), + url(r'^admin/', admin.site.urls), ] diff --git a/requirements.txt b/requirements.txt index 1df7250..d707b50 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,2 @@ -Django==1.8.4 +Django==2.0 tox==2.1.1 diff --git a/setup.py b/setup.py index 07b7793..1f3bd9b 100644 --- a/setup.py +++ b/setup.py @@ -9,17 +9,17 @@ setup( name='django-bulk-admin', - version='0.1.1', + version='0.1.2', packages=find_packages(exclude=('example_project*', 'screenshots',)), include_package_data=True, license='BSD', description='Django bulk admin enables you to bulk add, bulk edit, bulk upload and bulk select in django admin.', long_description=README, - url='https://github.com/purelabs/django-bulk-admin', - author='Ruben Grill', + url='https://github.com/jameslao/django-bulk-admin', + author='Ruben Grill, James Lao', author_email='ruben.grill@gmail.com', install_requires=[ - 'Django>=1.7', + 'Django>=4.0', ], classifiers=[ 'Environment :: Web Environment', @@ -28,12 +28,9 @@ 'License :: OSI Approved :: BSD License', 'Operating System :: OS Independent', 'Programming Language :: Python', - 'Programming Language :: Python :: 2', - 'Programming Language :: Python :: 2.7', - 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.2', - 'Programming Language :: Python :: 3.3', - 'Programming Language :: Python :: 3.4', + 'Programming Language :: Python :: 3.10', + 'Programming Language :: Python :: 3.11', + 'Programming Language :: Python :: 3.12', 'Topic :: Software Development :: Libraries :: Python Modules', ], ) diff --git a/tox.ini b/tox.ini index 63e9f97..f45f4a9 100644 --- a/tox.ini +++ b/tox.ini @@ -1,15 +1,14 @@ [tox] envlist = - py{27,32,33,34}-django{17,18} + py2-django1_11, + py3-django{1_11,2_0} [testenv] basepython = - py27: python2.7 - py32: python3.2 - py33: python3.3 - py34: python3.4 + py2: python2 + py3: python3 commands = make test deps = - django17: Django>=1.7,<1.8 - django18: Django>=1.8,<1.9 + django1_11: Django>=1.11,<1.12 + django2_0: Django>=2.0,<2.1 whitelist_externals = make