Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 82 additions & 10 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -1,13 +1,42 @@
name: Test

on: push
on: [push, pull_request]

jobs:
build:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: [3.7, 3.8, 3.9]
include:
- django-version: "2.2"
python-version: "3.8"
- django-version: "2.2"
python-version: "3.8"
grappelli: "1"
- django-version: "3.2"
python-version: "3.9"
- django-version: "3.2"
python-version: "3.10"
grappelli: "1"
- django-version: "4.2"
python-version: "3.10"
- django-version: "4.2"
python-version: "3.11"
grappelli: "1"
- django-version: "5.1"
python-version: "3.12"
- django-version: "5.2"
python-version: "3.12"
- django-version: "5.2"
python-version: "3.13"
grappelli: "1"

runs-on: ubuntu-latest
name: Django ${{ matrix.django-version }} (Python ${{ matrix.python-version }})${{ matrix.grappelli == '1' && ' + grappelli' || '' }}${{ matrix.s3 == '1' && ' + s3' || '' }}
env:
PYTHON: ${{ matrix.python-version }}
DJANGO: ${{ matrix.django-version }}
GRAPPELLI: ${{ matrix.grappelli || '0' }}

steps:
- uses: actions/checkout@v3
Expand All @@ -17,16 +46,59 @@ jobs:
with:
python-version: ${{ matrix.python-version }}

- name: Setup chromedriver
uses: nanasess/setup-chromedriver@v1.0.5

- name: Install dependencies
- name: Install tox
run: |
python -m pip install --upgrade pip
pip install tox tox-gh-actions
python3 -m pip install tox tox-gh-actions

- name: Test with tox
- name: Run tests
run: |
tox -- -v --selenosis-driver=chrome-headless || \
tox -- -v --selenosis-driver=chrome-headless || \
tox -- -v --selenosis-driver=chrome-headless

- name: Upload junit xml
if: always()
uses: actions/upload-artifact@v4
with:
name: junit-reports-django-${{ matrix.django-version }}-python${{ matrix.python-version }}${{ matrix.grappelli == '1' && '-grappelli' || '' }}${{ matrix.s3 == '1' && '-s3' || '' }}-${{ github.sha }}
path: reports/*.xml
overwrite: true

- name: Combine coverage
run: tox -e coverage-report

- name: Upload coverage
uses: codecov/codecov-action@v5
with:
name: ${{ github.workflow }}
files: .tox/coverage/coverage.xml
env_vars: "DJANGO,GRAPPELLI,PYTHON"
token: ${{ secrets.CODECOV_TOKEN }}

report:
if: always()
needs: build
runs-on: ubuntu-latest
name: "Report Test Results"
steps:
- uses: actions/download-artifact@v4
with:
merge-multiple: true

- name: Publish Unit Test Results
if: always()
uses: mikepenz/action-junit-report@1a91e26932fb7ba410a31fab1f09266a96d29971
with:
report_paths: ./*.xml
require_tests: true
fail_on_failure: true
check_name: Test Report
github_token: ${{ secrets.GITHUB_TOKEN }}

success:
needs: [report]
runs-on: ubuntu-latest
name: Test Successful
steps:
- name: Success
run: echo Test Successful
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,6 @@ ghostdriver.log
.tox
venv/
.python-version
reports
coverage.xml
.coverage
6 changes: 2 additions & 4 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,8 @@ developers at `The Atlantic <http://www.theatlantic.com/>`_.
Support
=======

Being that Django added select2 support in 2.0, we will support up to that version
for compatibility purposes.

* ~=v3.0: Python >=3.7,<3.9 | Django 2.2,3.1,3.2 (current release)
django-select2-forms should work with all currently supported releases as well
as the two most recent unsupported LTS versions.

Local Development & Testing
===========================
Expand Down
60 changes: 60 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
[build-system]
build-backend = "setuptools.build_meta"
requires = ["setuptools>=75.3.2"]

[project]
name = "django-select2-forms"
dynamic = ["version"]
description = "Django form fields using the Select2 jQuery plugin"
readme = "README.rst"
license = { text = "BSD-2-Clause" }
requires-python = ">=3"
authors = [
{ name = "The Atlantic", email = "programmers@theatlantic.com" },
]
classifiers = [
"Development Status :: 5 - Production/Stable",
"Environment :: Web Environment",
"Framework :: Django",
"Framework :: Django :: 2.2",
"Framework :: Django :: 3.2",
"Framework :: Django :: 4.2",
"Framework :: Django :: 5.0",
"Framework :: Django :: 5.1",
"Framework :: Django :: 5.2",
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
]
dependencies = [
"django-sortedm2m",
]

[project.urls]
Homepage = "https://github.com/theatlantic/django-select2-forms"

[tool.setuptools]
zip-safe = false
platforms = ["any"]
include-package-data = true

[tool.setuptools.packages.find]
include = ["select2*"]
namespaces = false

[tool.setuptools.dynamic]
version = { attr = "select2.__version__" }
readme = { file = ["README.rst"] }

[tool.pytest.ini_options]
python_files = "tests.py test_*.py *_test.py"
DJANGO_SETTINGS_MODULE = "tests.settings"
addopts = "--tb=short --create-db --cov=select2 --cov-branch --cov-report=xml"
django_find_project = false
testpaths = "tests"
pythonpath = "."
7 changes: 1 addition & 6 deletions select2/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1 @@
import pkg_resources

try:
__version__ = pkg_resources.get_distribution('django-select2-forms').version
except pkg_resources.DistributionNotFound:
__version__ = None
__version__ = "3.1.0"
18 changes: 9 additions & 9 deletions select2/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,7 @@ def choices(self):

@choices.setter
def choices(self, value):
self._set_choices(value)

def _set_choices(self, value):
self._choices = value
super(self.__class__, self.__class__).choices.__set__(self, value)


class ChoiceField(Select2FieldMixin, forms.ChoiceField):
Expand Down Expand Up @@ -133,12 +130,15 @@ def __init__(self, search_field=None, case_sensitive=False, *args, **kwargs):
self.choice_iterator_cls = kwargs.pop('choice_iterator_cls', self.choice_iterator_cls)
super(Select2ModelFieldMixin, self).__init__(*args, **kwargs)

def _get_choices(self):
if hasattr(self, '_choices'):
return self._choices
return self.choice_iterator_cls(self)
@property
def choices(self):
if not hasattr(self, '_choices'):
return self.choice_iterator_cls(self)
return self._choices

choices = property(_get_choices, forms.ChoiceField._set_choices)
@choices.setter
def choices(self, value):
super(self.__class__, self.__class__).choices.__set__(self, value)


class ModelChoiceField(Select2ModelFieldMixin, forms.ModelChoiceField):
Expand Down
3 changes: 3 additions & 0 deletions select2/static/select2/js/select2.jquery_ready.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ var DjangoSelect2 = window.DjangoSelect2 || {};
DjangoSelect2.init(this);
});
$(document).on('formset:added', function(event, $form) {
if (typeof $form === "undefined") {
$form = $(event.target);
}
$form.find('.django-select2:not([name*="__prefix__"])').each(function() {
DjangoSelect2.init(this);
});
Expand Down
42 changes: 2 additions & 40 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,41 +1,3 @@
#!/usr/bin/env python
import codecs
import os
from setuptools import setup, find_packages
from setuptools import setup

readme_rst = os.path.join(os.path.dirname(__file__), 'README.rst')

setup(
name='django-select2-forms',
version='3.0.0',
description='Django form fields using the Select2 jQuery plugin',
long_description=codecs.open(readme_rst, encoding='utf-8').read(),
author='Frankie Dintino',
author_email='fdintino@theatlantic.com',
url='https://github.com/theatlantic/django-select2-forms',
packages=find_packages(),
license='BSD',
platforms='any',
install_requires=[
'django-sortedm2m',
],
classifiers=[
'Development Status :: 5 - Production/Stable',
'Environment :: Web Environment',
'Intended Audience :: Developers',
'Operating System :: OS Independent',
'Programming Language :: Python',
'Framework :: Django',
'Framework :: Django :: 2.2',
'Framework :: Django :: 3.1',
'Framework :: Django :: 3.2',
'Programming Language :: Python',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3.9',

],
include_package_data=True,
zip_safe=False
)
setup()
12 changes: 12 additions & 0 deletions tests/admin.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from django.conf import settings
from django.contrib import admin

from .models import Publisher, Author, Book, Library
Expand All @@ -7,6 +8,17 @@ class BookInline(admin.StackedInline):
model = Book
extra = 0

@property
def classes(self):
if "grappelli" in settings.INSTALLED_APPS:
return ("grp-collapse grp-open",)
else:
return None

@property
def inline_classes(self):
return self.classes


@admin.register(Library)
class LibraryAdmin(admin.ModelAdmin):
Expand Down
7 changes: 7 additions & 0 deletions tests/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@
'tests',
]

try:
import grappelli # noqa
except ImportError:
pass
else:
INSTALLED_APPS.insert(0, 'grappelli')

MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
Expand Down
12 changes: 8 additions & 4 deletions tests/test_admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from django.conf import settings
from selenosis.testcases import AdminSelenosisTestCase
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By

from .models import Author, Publisher, Book, Library

Expand Down Expand Up @@ -93,7 +94,8 @@ def get_count():
yield el

def get_dropdown_count(self):
return len(self.selenium.find_elements_by_css_selector(
return len(self.selenium.find_elements(
By.CSS_SELECTOR,
'.select2-drop-active .select2-results '
'.select2-result-selectable:not(.select2-selected)'))

Expand Down Expand Up @@ -260,12 +262,14 @@ def test_m2m_ajax_custom_search_field(self):
def test_inline_add_init(self):
if django.VERSION < (1, 9):
raise unittest.SkipTest("Django 1.8 does not have the formset:added event")
if 'grappelli' in settings.INSTALLED_APPS:
raise unittest.SkipTest("django-grappelli does not have the formset:added event")
library = Library.objects.create(name="Princeton University Library")
columbia_univ_press = Publisher.objects.get(name='Columbia University Press')
self.load_admin(library)
with self.clickable_selector(".add-row a") as el:
if "grappelli" in settings.INSTALLED_APPS:
add_row_selector = ".grp-add-handler:not(.grp-icon)"
else:
add_row_selector = ".add-row a"
with self.clickable_selector(add_row_selector) as el:
el.click()
with self.clickable_selector('#id_book_set-0-title') as el:
el.send_keys('Difference and Repetition')
Expand Down
Loading