kopia lustrzana https://github.com/wagtail/wagtail
Drop support for Django <3.2
rodzic
e27af42fdf
commit
d6d43338ef
|
@ -17,18 +17,17 @@ on:
|
|||
# - test runs with USE_EMAIL_USER_MODEL=yes and DISABLE_TIMEZONE=yes
|
||||
|
||||
# Current configuration:
|
||||
# - django 3.0, python 3.7, sqlite
|
||||
# - django 3.1, python 3.7, postgres
|
||||
# - django 3.2, python 3.8, postgres
|
||||
# - django 3.2, python 3.9, mysql
|
||||
# - django 3.2, python 3.10, sqlite
|
||||
# - django 3.2, python 3.9, postgres, USE_EMAIL_USER_MODEL=yes
|
||||
# - django 3.2, python 3.7, postgres
|
||||
# - django 3.2, python 3.8, mysql
|
||||
# - django 3.2, python 3.9, sqlite
|
||||
# - django 4.0, python 3.9, mysql (allow failures)
|
||||
# - django 3.2, python 3.10, postgres, USE_EMAIL_USER_MODEL=yes
|
||||
# - django 3.2, python 3.10, postgres, DISABLE_TIMEZONE=yes
|
||||
# - django stable/4.0.x, python 3.9, postgres (allow failures)
|
||||
# - django stable/4.0.x, python 3.10, postgres (allow failures)
|
||||
# - django main, python 3.10, postgres (allow failures)
|
||||
# - elasticsearch 5, django 3.0, python 3.7, sqlite
|
||||
# - elasticsearch 6, django 3.1, python 3.7, postgres
|
||||
# - elasticsearch 7, django 3.2, python 3.8, postgres
|
||||
# - elasticsearch 5, django 3.2, python 3.7, sqlite
|
||||
# - elasticsearch 6, django 3.2, python 3.7, postgres
|
||||
# - elasticsearch 7, django 4.0, python 3.8, postgres (allow failures)
|
||||
# - elasticsearch 7, django 3.2, python 3.9, sqlite, USE_EMAIL_USER_MODEL=yes
|
||||
|
||||
jobs:
|
||||
|
@ -37,10 +36,8 @@ jobs:
|
|||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- python: "3.7"
|
||||
django: "Django>=3.0,<3.1"
|
||||
- python: "3.10"
|
||||
django: "Django>=3.1,<3.2"
|
||||
- python: "3.9"
|
||||
django: "Django>=3.2,<3.3"
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
@ -66,20 +63,17 @@ jobs:
|
|||
matrix:
|
||||
include:
|
||||
- python: "3.7"
|
||||
django: "Django>=3.1,<3.2"
|
||||
experimental: false
|
||||
- python: "3.8"
|
||||
django: "Django>=3.2,<3.3"
|
||||
experimental: false
|
||||
- python: "3.9"
|
||||
django: "Django>=3.2,<3.3"
|
||||
emailuser: emailuser
|
||||
experimental: false
|
||||
- python: "3.10"
|
||||
django: "Django>=3.2,<3.3"
|
||||
notz: notz
|
||||
experimental: false
|
||||
- python: "3.9"
|
||||
- python: "3.10"
|
||||
django: "Django>=3.2,<3.3"
|
||||
experimental: false
|
||||
emailuser: emailuser
|
||||
- python: "3.10"
|
||||
django: "git+https://github.com/django/django.git@stable/4.0.x#egg=Django"
|
||||
experimental: true
|
||||
- python: "3.10"
|
||||
|
@ -118,11 +112,16 @@ jobs:
|
|||
|
||||
test-mysql:
|
||||
runs-on: ubuntu-latest
|
||||
continue-on-error: ${{ matrix.experimental }}
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- python: "3.9"
|
||||
- python: "3.8"
|
||||
django: "Django>=3.2,<3.3"
|
||||
experimental: false
|
||||
- python: "3.9"
|
||||
django: "Django>=4.0,<4.1"
|
||||
experimental: true
|
||||
|
||||
services:
|
||||
mysql:
|
||||
|
@ -162,7 +161,7 @@ jobs:
|
|||
matrix:
|
||||
include:
|
||||
- python: "3.7"
|
||||
django: "Django>=3.0,<3.1"
|
||||
django: "Django>=3.2,<3.3"
|
||||
steps:
|
||||
- name: Configure sysctl limits
|
||||
run: |
|
||||
|
@ -246,7 +245,7 @@ jobs:
|
|||
matrix:
|
||||
include:
|
||||
- python: "3.7"
|
||||
django: "Django>=3.1,<3.2"
|
||||
django: "Django>=3.2,<3.3"
|
||||
|
||||
services:
|
||||
postgres:
|
||||
|
@ -290,11 +289,13 @@ jobs:
|
|||
|
||||
test-postgres-elasticsearch7:
|
||||
runs-on: ubuntu-latest
|
||||
continue-on-error: ${{ matrix.experimental }}
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- python: "3.8"
|
||||
django: "Django>=3.2,<3.3"
|
||||
django: "Django>=4.0,<4.1"
|
||||
experimental: true
|
||||
|
||||
services:
|
||||
postgres:
|
||||
|
|
|
@ -4,6 +4,7 @@ Changelog
|
|||
2.16 (xx.xx.xxxx) - IN DEVELOPMENT
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
* Removed support for Django 3.0 and 3.1
|
||||
* Removed support for Python 3.6
|
||||
* Added persistent IDs for ListBlock items, allowing commenting and improvements to revision comparisons (Matt Westcott, Tidjani Dia)
|
||||
* Added Aging Pages report (Tidjani Dia)
|
||||
|
|
|
@ -56,11 +56,11 @@ _(If you are reading this on GitHub, the details here may not be indicative of t
|
|||
|
||||
Wagtail supports:
|
||||
|
||||
* Django 3.0.x, 3.1.x and 3.2.x
|
||||
* Django 3.2.x
|
||||
* Python 3.7, 3.8, 3.9 and 3.10
|
||||
* PostgreSQL, MySQL and SQLite as database backends
|
||||
|
||||
[Previous versions of Wagtail](https://docs.wagtail.io/en/stable/releases/upgrading.html#compatible-django-python-versions) additionally supported Python 2.7 and Django 1.x - 2.x.
|
||||
[Previous versions of Wagtail](https://docs.wagtail.io/en/stable/releases/upgrading.html#compatible-django-python-versions) additionally supported Python 2.7 and earlier Django versions.
|
||||
|
||||
---
|
||||
|
||||
|
|
|
@ -71,10 +71,11 @@ set a thread-local to indicate to all downstream code that AMP mode is active.
|
|||
Django uses thread-locals internally to track the currently active language
|
||||
for the request.
|
||||
|
||||
Please be aware though: In Django 3.x and above, you will need to use an
|
||||
``asgiref.Local`` instead.
|
||||
This is because Django 3.x handles multiple requests in a single thread
|
||||
so thread-locals will no longer be unique to a single request.
|
||||
Python implements thread-local data through the ``threading.local`` class,
|
||||
but as of Django 3.x, multiple requests can be handled in a single thread
|
||||
and so thread-locals will no longer be unique to a single request. Django
|
||||
therefore provides ``asgiref.Local`` as a drop-in replacement.
|
||||
|
||||
|
||||
Now let's create that thread-local and some utility functions to interact with it,
|
||||
save this module as ``amp_utils.py`` in an app in your project:
|
||||
|
@ -84,10 +85,9 @@ save this module as ``amp_utils.py`` in an app in your project:
|
|||
# <app>/amp_utils.py
|
||||
|
||||
from contextlib import contextmanager
|
||||
from threading import local
|
||||
from asgiref.local import Local
|
||||
|
||||
# FIXME: For Django 3.0 support, replace this with asgiref.Local
|
||||
_amp_mode_active = local()
|
||||
_amp_mode_active = Local()
|
||||
|
||||
@contextmanager
|
||||
def activate_amp_mode():
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
Wagtail provides the `wagtail start` command and project template to get you started with a new Wagtail project as quickly as possible, but it's easy to integrate Wagtail into an existing Django project too.
|
||||
|
||||
Wagtail is currently compatible with Django 3.0, 3.1 and 3.2. First, install the `wagtail` package from PyPI:
|
||||
Wagtail is currently compatible with Django 3.2. First, install the `wagtail` package from PyPI:
|
||||
|
||||
```sh
|
||||
$ pip install wagtail
|
||||
|
|
|
@ -43,6 +43,11 @@
|
|||
|
||||
## Upgrade considerations
|
||||
|
||||
### Removed support for Django 3.0 and 3.1
|
||||
|
||||
Django 3.0 and 3.1 are no longer supported as of this release; please upgrade to Django 3.2 or above before upgrading Wagtail.
|
||||
|
||||
|
||||
### Removed support for Python 3.6
|
||||
|
||||
Python 3.6 is no longer supported as of this release; please upgrade to Python 3.7 or above before upgrading Wagtail.
|
||||
|
|
|
@ -147,5 +147,5 @@ The compatible versions of Django and Python for each Wagtail release are:
|
|||
+-------------------+------------------------------+-----------------------------+
|
||||
| 2.15 LTS | 3.0, 3.1, 3.2 | 3.6, 3.7, 3.8, 3.9, 3.10 |
|
||||
+-------------------+------------------------------+-----------------------------+
|
||||
| 2.16 | 3.0, 3.1, 3.2 | 3.7, 3.8, 3.9, 3.10 |
|
||||
| 2.16 | 3.2 | 3.7, 3.8, 3.9, 3.10 |
|
||||
+-------------------+------------------------------+-----------------------------+
|
||||
|
|
4
setup.py
4
setup.py
|
@ -20,7 +20,7 @@ except ImportError:
|
|||
|
||||
|
||||
install_requires = [
|
||||
"Django>=3.0,<3.3",
|
||||
"Django>=3.2,<4.0",
|
||||
"django-modelcluster>=5.2,<6.0",
|
||||
"django-taggit>=1.0,<2.0",
|
||||
"django-treebeard>=4.2.0,<5.0,!=4.5",
|
||||
|
@ -114,8 +114,6 @@ https://github.com/wagtail/wagtail/.",
|
|||
'Programming Language :: Python :: 3.9',
|
||||
'Programming Language :: Python :: 3.10',
|
||||
'Framework :: Django',
|
||||
'Framework :: Django :: 3.0',
|
||||
'Framework :: Django :: 3.1',
|
||||
'Framework :: Django :: 3.2',
|
||||
'Framework :: Wagtail',
|
||||
'Topic :: Internet :: WWW/HTTP :: Site Management',
|
||||
|
|
6
tox.ini
6
tox.ini
|
@ -2,7 +2,7 @@
|
|||
skipsdist = True
|
||||
usedevelop = True
|
||||
|
||||
envlist = py{37,38,39,310}-dj{30,31,32,32stable,main}-{sqlite,postgres,mysql,mssql}-{elasticsearch7,elasticsearch6,elasticsearch5,noelasticsearch}-{customuser,emailuser}-{tz,notz},
|
||||
envlist = py{37,38,39,310}-dj{32,40stable,main}-{sqlite,postgres,mysql,mssql}-{elasticsearch7,elasticsearch6,elasticsearch5,noelasticsearch}-{customuser,emailuser}-{tz,notz},
|
||||
|
||||
[testenv]
|
||||
install_command = pip install -e ".[testing]" -U {opts} {packages}
|
||||
|
@ -22,10 +22,8 @@ deps =
|
|||
django-sendfile==0.3.6
|
||||
Embedly
|
||||
|
||||
dj30: Django~=3.0.0
|
||||
dj31: Django~=3.1.0
|
||||
dj32: Django~=3.2.0
|
||||
dj32stable: git+https://github.com/django/django.git@stable/3.2.x#egg=Django
|
||||
dj40stable: git+https://github.com/django/django.git@stable/4.0.x#egg=Django
|
||||
djmain: git+https://github.com/django/django.git@main#egg=Django
|
||||
|
||||
postgres: psycopg2>=2.6
|
||||
|
|
|
@ -139,14 +139,8 @@ class WagtailAdminPageForm(WagtailAdminModelForm):
|
|||
def is_valid(self):
|
||||
comments = self.formsets.get('comments')
|
||||
# Remove the comments formset if the management form is invalid
|
||||
if comments:
|
||||
try:
|
||||
# As of Django 3.2, this no longer raises an error
|
||||
has_form = comments.management_form.is_valid()
|
||||
except forms.ValidationError:
|
||||
has_form = False
|
||||
if not has_form:
|
||||
del self.formsets['comments']
|
||||
if comments and not comments.management_form.is_valid():
|
||||
del self.formsets['comments']
|
||||
return super().is_valid()
|
||||
|
||||
def clean(self):
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
import json
|
||||
import unittest
|
||||
|
||||
from django import VERSION as DJANGO_VERSION
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.models import Group, Permission
|
||||
from django.core import mail
|
||||
|
@ -35,18 +34,11 @@ class TestHome(TestCase, WagtailTestUtils):
|
|||
response = self.client.get(reverse('wagtailadmin_home'))
|
||||
self.assertEqual(response.status_code, 200)
|
||||
# check that media attached to menu items is correctly pulled in
|
||||
if DJANGO_VERSION >= (3, 1):
|
||||
self.assertContains(
|
||||
response,
|
||||
'<script src="/static/testapp/js/kittens.js"></script>',
|
||||
html=True
|
||||
)
|
||||
else:
|
||||
self.assertContains(
|
||||
response,
|
||||
'<script type="text/javascript" src="/static/testapp/js/kittens.js"></script>',
|
||||
html=True
|
||||
)
|
||||
self.assertContains(
|
||||
response,
|
||||
'<script src="/static/testapp/js/kittens.js"></script>',
|
||||
html=True
|
||||
)
|
||||
|
||||
# check that custom menu items (including classname / attrs parameters) are pulled in
|
||||
self.assertContains(
|
||||
|
@ -74,18 +66,11 @@ class TestHome(TestCase, WagtailTestUtils):
|
|||
self.assertContains(response, "<p>It looks like you're making a website. Would you like some help?</p>")
|
||||
|
||||
# check that media attached to dashboard panels is correctly pulled in
|
||||
if DJANGO_VERSION >= (3, 1):
|
||||
self.assertContains(
|
||||
response,
|
||||
'<script src="/static/testapp/js/clippy.js"></script>',
|
||||
html=True
|
||||
)
|
||||
else:
|
||||
self.assertContains(
|
||||
response,
|
||||
'<script type="text/javascript" src="/static/testapp/js/clippy.js"></script>',
|
||||
html=True
|
||||
)
|
||||
self.assertContains(
|
||||
response,
|
||||
'<script src="/static/testapp/js/clippy.js"></script>',
|
||||
html=True
|
||||
)
|
||||
|
||||
def test_summary_items(self):
|
||||
response = self.client.get(reverse('wagtailadmin_home'))
|
||||
|
|
|
@ -3,7 +3,6 @@ import warnings
|
|||
from collections import OrderedDict
|
||||
from functools import reduce
|
||||
|
||||
from django import VERSION as DJANGO_VERSION
|
||||
from django.contrib.postgres.search import SearchQuery, SearchRank, SearchVector
|
||||
from django.db import DEFAULT_DB_ALIAS, NotSupportedError, connections, transaction
|
||||
from django.db.models import Avg, Count, F, Manager, Q, TextField, Value
|
||||
|
@ -21,7 +20,7 @@ from wagtail.search.utils import ADD, MUL, OR
|
|||
from wagtail.utils.deprecation import RemovedInWagtail217Warning
|
||||
|
||||
from .models import IndexEntry
|
||||
from .query import Lexeme, RawSearchQuery
|
||||
from .query import Lexeme
|
||||
from .utils import (
|
||||
get_content_type_pk, get_descendants_content_types_pks, get_postgresql_connections,
|
||||
get_sql_weights, get_weight)
|
||||
|
@ -387,10 +386,7 @@ class PostgresSearchQueryCompiler(BaseSearchQueryCompiler):
|
|||
else:
|
||||
lexemes |= new_lexeme
|
||||
|
||||
if DJANGO_VERSION >= (3, 1):
|
||||
return SearchQuery(lexemes, search_type='raw', config=config)
|
||||
else:
|
||||
return RawSearchQuery(lexemes, config=config)
|
||||
return SearchQuery(lexemes, search_type='raw', config=config)
|
||||
|
||||
elif isinstance(query, Phrase):
|
||||
return SearchQuery(query.query_string, search_type='phrase')
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
# If that PR gets merged, we should be able to replace this with the version in Django.
|
||||
|
||||
from django.contrib.postgres.search import SearchQueryCombinable, SearchQueryField
|
||||
from django.contrib.postgres.search import SearchQueryField
|
||||
from django.db.models.expressions import Expression, Value
|
||||
|
||||
|
||||
|
@ -85,46 +85,3 @@ class CombinedLexeme(LexemeCombinable):
|
|||
combined_sql = '({} {} {})'.format(lsql, self.connector, rsql)
|
||||
combined_value = combined_sql % tuple(value_params)
|
||||
return '%s', [combined_value]
|
||||
|
||||
|
||||
# This class is required for Django 3.0 support and below
|
||||
# In Django 3.1 onwards, we can replace this with SearchQuery(expression, search_type='raw')
|
||||
# The PR for the functionality we need is here: https://github.com/django/django/pull/12525
|
||||
class RawSearchQuery(SearchQueryCombinable, Expression):
|
||||
_output_field = SearchQueryField()
|
||||
|
||||
def __init__(self, expressions, output_field=None, *, config=None, invert=False):
|
||||
self.config = config
|
||||
self.invert = invert
|
||||
self.expressions = expressions
|
||||
super().__init__(output_field=output_field)
|
||||
|
||||
def resolve_expression(self, query=None, allow_joins=True, reuse=None, summarize=False, for_save=False):
|
||||
resolved = super().resolve_expression(query, allow_joins, reuse, summarize, for_save)
|
||||
if self.config:
|
||||
if not hasattr(self.config, 'resolve_expression'):
|
||||
resolved.config = Value(self.config).resolve_expression(query, allow_joins, reuse, summarize, for_save)
|
||||
else:
|
||||
resolved.config = self.config.resolve_expression(query, allow_joins, reuse, summarize, for_save)
|
||||
return resolved
|
||||
|
||||
def as_sql(self, compiler, connection):
|
||||
sql, params, = compiler.compile(self.expressions)
|
||||
|
||||
if self.config:
|
||||
config_sql, config_params = compiler.compile(self.config)
|
||||
template = 'to_tsquery({}::regconfig, {})'.format(config_sql, sql)
|
||||
params = config_params + params
|
||||
else:
|
||||
template = 'to_tsquery({})'.format(sql)
|
||||
if self.invert:
|
||||
template = '!!({})'.format(template)
|
||||
return template, params
|
||||
|
||||
def _combine(self, *args, **kwargs):
|
||||
combined = super()._combine(*args, **kwargs)
|
||||
combined.output_field = SearchQueryField()
|
||||
return combined
|
||||
|
||||
def __invert__(self):
|
||||
return type(self)(self.lexeme, config=self.config, invert=not self.invert)
|
||||
|
|
|
@ -2,12 +2,7 @@ import uuid
|
|||
|
||||
from warnings import warn
|
||||
|
||||
|
||||
try:
|
||||
from asgiref.local import Local
|
||||
except ImportError: # fallback for Django <3.0
|
||||
from threading import local as Local
|
||||
|
||||
from asgiref.local import Local
|
||||
from django.utils.functional import LazyObject
|
||||
|
||||
from wagtail.core import hooks
|
||||
|
|
|
@ -3,7 +3,6 @@ import warnings
|
|||
from collections import OrderedDict
|
||||
from functools import reduce
|
||||
|
||||
from django import VERSION as DJANGO_VERSION
|
||||
from django.contrib.postgres.search import SearchQuery, SearchRank, SearchVector
|
||||
from django.db import DEFAULT_DB_ALIAS, NotSupportedError, connections, transaction
|
||||
from django.db.models import Avg, Count, F, Manager, Q, TextField, Value
|
||||
|
@ -18,7 +17,7 @@ from ....models import IndexEntry
|
|||
from ....query import And, Boost, MatchAll, Not, Or, Phrase, PlainText
|
||||
from ....utils import ADD, MUL, OR, get_content_type_pk, get_descendants_content_types_pks
|
||||
from ...base import BaseSearchBackend, BaseSearchQueryCompiler, BaseSearchResults, FilterFieldError
|
||||
from .query import Lexeme, RawSearchQuery
|
||||
from .query import Lexeme
|
||||
from .weights import get_sql_weights, get_weight
|
||||
|
||||
|
||||
|
@ -375,10 +374,7 @@ class PostgresSearchQueryCompiler(BaseSearchQueryCompiler):
|
|||
else:
|
||||
lexemes |= new_lexeme
|
||||
|
||||
if DJANGO_VERSION >= (3, 1):
|
||||
return SearchQuery(lexemes, search_type='raw', config=config)
|
||||
else:
|
||||
return RawSearchQuery(lexemes, config=config)
|
||||
return SearchQuery(lexemes, search_type='raw', config=config)
|
||||
|
||||
elif isinstance(query, Phrase):
|
||||
return SearchQuery(query.query_string, search_type='phrase')
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from django.contrib.postgres.search import SearchQueryCombinable, SearchQueryField
|
||||
from django.contrib.postgres.search import SearchQueryField
|
||||
from django.db.models.expressions import Expression, Value
|
||||
|
||||
|
||||
|
@ -80,46 +80,3 @@ class CombinedLexeme(LexemeCombinable):
|
|||
combined_sql = '({} {} {})'.format(lsql, self.connector, rsql)
|
||||
combined_value = combined_sql % tuple(value_params)
|
||||
return '%s', [combined_value]
|
||||
|
||||
|
||||
# This class is required for Django 3.0 support and below
|
||||
# In Django 3.1 onwards, we can replace this with SearchQuery(expression, search_type='raw')
|
||||
# The PR for the functionality we need is here: https://github.com/django/django/pull/12525
|
||||
class RawSearchQuery(SearchQueryCombinable, Expression):
|
||||
_output_field = SearchQueryField()
|
||||
|
||||
def __init__(self, expressions, output_field=None, *, config=None, invert=False):
|
||||
self.config = config
|
||||
self.invert = invert
|
||||
self.expressions = expressions
|
||||
super().__init__(output_field=output_field)
|
||||
|
||||
def resolve_expression(self, query=None, allow_joins=True, reuse=None, summarize=False, for_save=False):
|
||||
resolved = super().resolve_expression(query, allow_joins, reuse, summarize, for_save)
|
||||
if self.config:
|
||||
if not hasattr(self.config, 'resolve_expression'):
|
||||
resolved.config = Value(self.config).resolve_expression(query, allow_joins, reuse, summarize, for_save)
|
||||
else:
|
||||
resolved.config = self.config.resolve_expression(query, allow_joins, reuse, summarize, for_save)
|
||||
return resolved
|
||||
|
||||
def as_sql(self, compiler, connection):
|
||||
sql, params, = compiler.compile(self.expressions)
|
||||
|
||||
if self.config:
|
||||
config_sql, config_params = compiler.compile(self.config)
|
||||
template = 'to_tsquery({}::regconfig, {})'.format(config_sql, sql)
|
||||
params = config_params + params
|
||||
else:
|
||||
template = 'to_tsquery({})'.format(sql)
|
||||
if self.invert:
|
||||
template = '!!({})'.format(template)
|
||||
return template, params
|
||||
|
||||
def _combine(self, *args, **kwargs):
|
||||
combined = super()._combine(*args, **kwargs)
|
||||
combined.output_field = SearchQueryField()
|
||||
return combined
|
||||
|
||||
def __invert__(self):
|
||||
return type(self)(self.lexeme, config=self.config, invert=not self.invert)
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import itertools
|
||||
import re
|
||||
|
||||
from django import VERSION as DJANGO_VERSION
|
||||
from django import template
|
||||
|
||||
from wagtail.core import hooks
|
||||
|
@ -44,18 +43,11 @@ def format_permissions(permission_bound_field):
|
|||
|
||||
# iterate over permission_bound_field to build a lookup of individual renderable
|
||||
# checkbox objects
|
||||
if DJANGO_VERSION < (3, 1):
|
||||
# checkbox.data['value'] gives the ID
|
||||
checkboxes_by_id = {
|
||||
int(checkbox.data['value']): checkbox
|
||||
for checkbox in permission_bound_field
|
||||
}
|
||||
else:
|
||||
# checkbox.data['value'] gives a ModelChoiceIteratorValue
|
||||
checkboxes_by_id = {
|
||||
int(checkbox.data['value'].value): checkbox
|
||||
for checkbox in permission_bound_field
|
||||
}
|
||||
# checkbox.data['value'] gives a ModelChoiceIteratorValue
|
||||
checkboxes_by_id = {
|
||||
int(checkbox.data['value'].value): checkbox
|
||||
for checkbox in permission_bound_field
|
||||
}
|
||||
|
||||
object_perms = []
|
||||
other_perms = []
|
||||
|
|
Ładowanie…
Reference in New Issue