[Django] #33724: Django 4.1 alpha - changing from list to set in `exclude` raises errors, and is not documented

4 views
Skip to first unread message

Django

unread,
May 19, 2022, 4:59:31 AM5/19/22
to django-...@googlegroups.com
#33724: Django 4.1 alpha - changing from list to set in `exclude` raises errors,
and is not documented
-----------------------------------------+------------------------
Reporter: אורי | Owner: nobody
Type: Uncategorized | Status: new
Component: Uncategorized | Version: 4.1
Severity: Normal | Keywords:
Triage Stage: Unreviewed | Has patch: 0
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
-----------------------------------------+------------------------
The commit:
https://github.com/django/django/commit/1ea7e3157d1f9b4db71e768d75ea57e47dbd49f9

My use case:

I used `def clean_fields` in a mixin inherited by some of my models:

{{{
class CleanAndValidateAllFieldsMixin(object):
def clean_fields(self, exclude=None):
"""
Allows to have different slug and username validators for Entity
and User.
"""
if (exclude is None):
exclude = []

self.clean_all_fields(exclude=exclude)

try:
super().clean_fields(exclude=exclude)
except ValidationError as e:
errors = e.error_dict
else:
errors = {}

self.validate_all_fields(errors=errors, exclude=exclude)

def clean_all_fields(self, exclude=None):
pass

}}}

In some of the models that use it, I defined `clean_fields` and added
values to `exclude`:

{{{
def clean_fields(self, exclude=None):
self.normalize_slug_and_username()
self.validate_username_for_slug()
self.validate_username_required()
self.validate_username_unique()

if (exclude is None):
exclude = []

# Reserved username can be less than 6 characters, and any
alphanumeric sequence.
exclude += ['username', 'slug']

return super().clean_fields(exclude=exclude)
}}}

{{{
def clean_fields(self, exclude=None):
"""
Allows to have different slug and username validators for Entity
and User.
"""
if (exclude is None):
exclude = []

# If special username is true, don't validate username.
if (self.special_username):
self.normalize_slug_and_username()
self.validate_username_for_slug()
self.validate_username_required()
self.validate_username_unique()
exclude += ['username', 'slug']

return super().clean_fields(exclude=exclude)
}}}

The results: model tests fail with Django 4.1 alpha:

{{{
======================================================================
ERROR: test_username_too_long_exception_4
(speedy.core.accounts.tests.test_models.ReservedUsernameHebrewTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "...\speedy\core\accounts\tests\test_models.py", line 395, in
test_username_too_long_exception_4
reserved_username.save()
File "...\speedy\core\base\models.py", line 21, in save
return super().save(*args, **kwargs)
File "...\speedy\core\base\models.py", line 12, in save
self.full_clean()
File "...\.venv_3.9\lib\site-packages\django\db\models\base.py", line
1464, in full_clean
self.clean_fields(exclude=exclude)
File "...\speedy\core\accounts\models.py", line 182, in clean_fields
exclude += ['username', 'slug']
TypeError: unsupported operand type(s) for +=: 'set' and 'list'

----------------------------------------------------------------------
}}}

Is `exclude` a set now (instead of a list) and where is it documented? If
it's not documented, please document it. I didn't find it documented on
https://docs.djangoproject.com/en/dev/releases/4.1/.

What is the best written code to change the line `exclude += ['username',
'slug']` in my code? Is it `exclude |= set(['username', 'slug'])` or
`exclude |= {'username', 'slug'}`? Or should I convert to list and then
back to set?

What is the reason `exclude` was changed to a set?

How should `exclude` be defined in `clean_fields` and what should I do if
I receive `exclude is None`?

Thanks,
Uri.

--
Ticket URL: <https://code.djangoproject.com/ticket/33724>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

Reply all
Reply to author
Forward
0 new messages