diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 6fb3bfb..089252e 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -13,8 +13,6 @@ jobs: # and https://docs.djangoproject.com/en/4.2/faq/install/#what-python-version-can-i-use-with-django matrix: include: - - { dj: "4.1.*", py: "3.8" } - - { dj: "4.1.*", py: "3.11" } - { dj: "4.2.*", py: "3.8" } - { dj: "4.2.*", py: "3.12" } - { dj: "5.0.*", py: "3.10" } diff --git a/CHANGES.rst b/CHANGES.rst index 21915b6..24e5353 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,3 +1,7 @@ +development (unreleased) +------------------- +* Fix error with Django>=4.1.3: + 0.1.12 (2020-02-20) ------------------- diff --git a/example/app/test_msf_select.py b/example/app/test_msf_select.py new file mode 100644 index 0000000..b98c0dd --- /dev/null +++ b/example/app/test_msf_select.py @@ -0,0 +1,19 @@ +from django.test.testcases import TestCase + +from .models import Book + + +class MsfSelectTestCase(TestCase): + fixtures = ['app_data.json'] + + def test_valid_select(self): + """ + Should be able to use a multiselectfield result to select + See + https://github.com/goinnn/django-multiselectfield/pull/135 + """ + book = Book.objects.first() + result = Book.objects.filter(categories=book.categories).only('pk') + self.assertEqual(len(result), 1) + self.assertEqual(result[0].pk, book.pk) + self.assertIn(member='1,3,5', container=str(result.query)) diff --git a/multiselectfield/db/fields.py b/multiselectfield/db/fields.py index 8fbcd4d..35aaa51 100644 --- a/multiselectfield/db/fields.py +++ b/multiselectfield/db/fields.py @@ -36,17 +36,6 @@ def wrapper(cls): return wrapper -class MSFList(list): - - def __init__(self, choices, *args, **kwargs): - self.choices = choices - super(MSFList, self).__init__(*args, **kwargs) - - def __str__(msgl): - l = [msgl.choices.get(int(i)) if i.isdigit() else msgl.choices.get(i) for i in msgl] - return ', '.join([str(s) for s in l]) - - class MultiSelectField(models.CharField): """ Choice values can not contain commas. """ diff --git a/multiselectfield/utils.py b/multiselectfield/utils.py index c08ff48..35a25d3 100644 --- a/multiselectfield/utils.py +++ b/multiselectfield/utils.py @@ -14,6 +14,23 @@ # You should have received a copy of the GNU Lesser General Public License # along with this programe. If not, see . +from __future__ import annotations + +from collections import UserList +from typing import Optional, Union + +from django.db.models.sql.query import Query + + +class _FakeSqlVal(UserList): + + contains_aggregate = False + contains_column_references = False + contains_over_clause = False + + def __str__(self): + return ','.join(map(str, self)) + class MSFList(list): @@ -22,8 +39,20 @@ def __init__(self, choices, *args, **kwargs): super(MSFList, self).__init__(*args, **kwargs) def __str__(msgl): - msg_list = [msgl.choices.get(int(i)) if i.isdigit() else msgl.choices.get(i) for i in msgl] - return ', '.join([str(s) for s in msg_list]) + msg_list = [ + msgl.choices.get(int(i)) if i.isdigit() else msgl.choices.get(i) + for i in msgl] + return ', '.join(str(s) for s in msg_list) + + def resolve_expression( + self, query: Query = None, allow_joins: bool = True, + reuse: Optional[bool] = None, summarize: bool = False, + for_save: bool = False) -> Union[list, _FakeSqlVal]: + if for_save: + result = _FakeSqlVal(self) + else: + result = list(self) + return result def get_max_length(choices, max_length, default=200): diff --git a/setup.py b/setup.py index 4dced04..f9b0b34 100644 --- a/setup.py +++ b/setup.py @@ -18,7 +18,8 @@ import codecs import os -from setuptools import setup, find_packages + +from setuptools import find_packages, setup def read(*rnames):