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

6 views
Skip to first unread message

Django

unread,
May 19, 2022, 5:25:33 AM5/19/22
to django-...@googlegroups.com
#33724: Changing from list to set in `exclude` raises errors, and is not
documented.
-------------------------------------+-------------------------------------
Reporter: אורי | Owner: nobody
Type: Bug | Status: new
Component: Database layer | Version: 4.1
(models, ORM) |
Severity: Release blocker | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Mariusz Felisiak):

* type: Uncategorized => Bug
* component: Uncategorized => Database layer (models, ORM)
* severity: Normal => Release blocker
* stage: Unreviewed => Accepted


Comment:

Agreed, we should document this change, maybe:
{{{#!diff
diff --git a/docs/ref/models/instances.txt b/docs/ref/models/instances.txt
index 9aa9486f4a..b844ac3ea4 100644
--- a/docs/ref/models/instances.txt
+++ b/docs/ref/models/instances.txt
@@ -252,9 +252,9 @@ The first step ``full_clean()`` performs is to clean
each individual field.
.. method:: Model.clean_fields(exclude=None)

This method will validate all fields on your model. The optional
``exclude``
-argument lets you provide a list of field names to exclude from
validation. It
-will raise a :exc:`~django.core.exceptions.ValidationError` if any fields
fail
-validation.
+argument lets you provide a set or list of field names to exclude from
+validation. It will raise a
:exc:`~django.core.exceptions.ValidationError` if
+any fields fail validation.

The second step ``full_clean()`` performs is to call
:meth:`Model.clean()`.
This method should be overridden to perform custom validation on your
model.
@@ -355,8 +355,8 @@ uniqueness constraints defined via
:attr:`.Field.unique`,
:attr:`.Field.unique_for_date`, :attr:`.Field.unique_for_month`,
:attr:`.Field.unique_for_year`, or :attr:`Meta.unique_together
<django.db.models.Options.unique_together>` on your model instead of
individual
-field values. The optional ``exclude`` argument allows you to provide a
list of
-field names to exclude from validation. It will raise a
+field values. The optional ``exclude`` argument allows you to provide a
set or
+list of field names to exclude from validation. It will raise a
:exc:`~django.core.exceptions.ValidationError` if any fields fail
validation.

:class:`~django.db.models.UniqueConstraint`\s defined in the
@@ -380,8 +380,8 @@ Finally, ``full_clean()`` will check any other
constraints on your model.

This method validates all constraints defined in
:attr:`Meta.constraints <django.db.models.Options.constraints>`. The
-optional ``exclude`` argument allows you to provide a list of field names
to
-exclude from validation. It will raise a
+optional ``exclude`` argument allows you to provide a set or list of
field
+names to exclude from validation. It will raise a
:exc:`~django.core.exceptions.ValidationError` if any constraints fail
validation.

diff --git a/docs/releases/4.1.txt b/docs/releases/4.1.txt
index 7b922256ec..447824ab7f 100644
--- a/docs/releases/4.1.txt
+++ b/docs/releases/4.1.txt
@@ -561,6 +561,10 @@ Miscellaneous
``URLResolver._callback_strs``, and ``URLPattern.lookup_str()`` are
moved to ``django.contrib.admindocs.utils``.

+* Custom :meth:`.Model.clean_fields`, :meth:`.Model.validate_unique`, and
+ :meth:`.Model.validate_constraints` methods must handle the ``exclude``
+ values passed as ``set``.
+
.. _deprecated-features-4.1:

Features deprecated in 4.1
}}}

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

`exclude` is used only for containment checks, so we decided to use `set`
for performance reasons.

> 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?

Personally I would use `exclude |= {'username', 'slug'}` or
{{{
exclude.add('username')
exclude.add('slug')
}}}

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

Reply all
Reply to author
Forward
0 new messages