summaryrefslogtreecommitdiff
path: root/django/db/models/base.py
diff options
context:
space:
mode:
authordjango-bot <ops@djangoproject.com>2022-02-03 20:24:19 +0100
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2022-02-07 20:37:05 +0100
commit9c19aff7c7561e3a82978a272ecdaad40dda5c00 (patch)
treef0506b668a013d0063e5fba3dbf4863b466713ba /django/db/models/base.py
parentf68fa8b45dfac545cfc4111d4e52804c86db68d3 (diff)
Refs #33476 -- Reformatted code with Black.
Diffstat (limited to 'django/db/models/base.py')
-rw-r--r--django/db/models/base.py841
1 files changed, 519 insertions, 322 deletions
diff --git a/django/db/models/base.py b/django/db/models/base.py
index 37f6a3dd58..8127a9895a 100644
--- a/django/db/models/base.py
+++ b/django/db/models/base.py
@@ -9,28 +9,42 @@ from django.apps import apps
from django.conf import settings
from django.core import checks
from django.core.exceptions import (
- NON_FIELD_ERRORS, FieldDoesNotExist, FieldError, MultipleObjectsReturned,
- ObjectDoesNotExist, ValidationError,
+ NON_FIELD_ERRORS,
+ FieldDoesNotExist,
+ FieldError,
+ MultipleObjectsReturned,
+ ObjectDoesNotExist,
+ ValidationError,
)
from django.db import (
- DEFAULT_DB_ALIAS, DJANGO_VERSION_PICKLE_KEY, DatabaseError, connection,
- connections, router, transaction,
-)
-from django.db.models import (
- NOT_PROVIDED, ExpressionWrapper, IntegerField, Max, Value,
+ DEFAULT_DB_ALIAS,
+ DJANGO_VERSION_PICKLE_KEY,
+ DatabaseError,
+ connection,
+ connections,
+ router,
+ transaction,
)
+from django.db.models import NOT_PROVIDED, ExpressionWrapper, IntegerField, Max, Value
from django.db.models.constants import LOOKUP_SEP
from django.db.models.constraints import CheckConstraint, UniqueConstraint
from django.db.models.deletion import CASCADE, Collector
from django.db.models.fields.related import (
- ForeignObjectRel, OneToOneField, lazy_related_operation, resolve_relation,
+ ForeignObjectRel,
+ OneToOneField,
+ lazy_related_operation,
+ resolve_relation,
)
from django.db.models.functions import Coalesce
from django.db.models.manager import Manager
from django.db.models.options import Options
from django.db.models.query import F, Q
from django.db.models.signals import (
- class_prepared, post_init, post_save, pre_init, pre_save,
+ class_prepared,
+ post_init,
+ post_save,
+ pre_init,
+ pre_save,
)
from django.db.models.utils import make_model_tuple
from django.utils.encoding import force_str
@@ -41,10 +55,10 @@ from django.utils.translation import gettext_lazy as _
class Deferred:
def __repr__(self):
- return '<Deferred field>'
+ return "<Deferred field>"
def __str__(self):
- return '<Deferred field>'
+ return "<Deferred field>"
DEFERRED = Deferred()
@@ -58,19 +72,24 @@ def subclass_exception(name, bases, module, attached_to):
that the returned exception class will be added as an attribute to the
'attached_to' class.
"""
- return type(name, bases, {
- '__module__': module,
- '__qualname__': '%s.%s' % (attached_to.__qualname__, name),
- })
+ return type(
+ name,
+ bases,
+ {
+ "__module__": module,
+ "__qualname__": "%s.%s" % (attached_to.__qualname__, name),
+ },
+ )
def _has_contribute_to_class(value):
# Only call contribute_to_class() if it's bound.
- return not inspect.isclass(value) and hasattr(value, 'contribute_to_class')
+ return not inspect.isclass(value) and hasattr(value, "contribute_to_class")
class ModelBase(type):
"""Metaclass for all models."""
+
def __new__(cls, name, bases, attrs, **kwargs):
super_new = super().__new__
@@ -81,12 +100,12 @@ class ModelBase(type):
return super_new(cls, name, bases, attrs)
# Create the class.
- module = attrs.pop('__module__')
- new_attrs = {'__module__': module}
- classcell = attrs.pop('__classcell__', None)
+ module = attrs.pop("__module__")
+ new_attrs = {"__module__": module}
+ classcell = attrs.pop("__classcell__", None)
if classcell is not None:
- new_attrs['__classcell__'] = classcell
- attr_meta = attrs.pop('Meta', None)
+ new_attrs["__classcell__"] = classcell
+ attr_meta = attrs.pop("Meta", None)
# Pass all attrs without a (Django-specific) contribute_to_class()
# method to type.__new__() so that they're properly initialized
# (i.e. __set_name__()).
@@ -98,16 +117,16 @@ class ModelBase(type):
new_attrs[obj_name] = obj
new_class = super_new(cls, name, bases, new_attrs, **kwargs)
- abstract = getattr(attr_meta, 'abstract', False)
- meta = attr_meta or getattr(new_class, 'Meta', None)
- base_meta = getattr(new_class, '_meta', None)
+ abstract = getattr(attr_meta, "abstract", False)
+ meta = attr_meta or getattr(new_class, "Meta", None)
+ base_meta = getattr(new_class, "_meta", None)
app_label = None
# Look for an application configuration to attach the model to.
app_config = apps.get_containing_app_config(module)
- if getattr(meta, 'app_label', None) is None:
+ if getattr(meta, "app_label", None) is None:
if app_config is None:
if not abstract:
raise RuntimeError(
@@ -119,33 +138,43 @@ class ModelBase(type):
else:
app_label = app_config.label
- new_class.add_to_class('_meta', Options(meta, app_label))
+ new_class.add_to_class("_meta", Options(meta, app_label))
if not abstract:
new_class.add_to_class(
- 'DoesNotExist',
+ "DoesNotExist",
subclass_exception(
- 'DoesNotExist',
+ "DoesNotExist",
tuple(
- x.DoesNotExist for x in parents if hasattr(x, '_meta') and not x._meta.abstract
- ) or (ObjectDoesNotExist,),
+ x.DoesNotExist
+ for x in parents
+ if hasattr(x, "_meta") and not x._meta.abstract
+ )
+ or (ObjectDoesNotExist,),
module,
- attached_to=new_class))
+ attached_to=new_class,
+ ),
+ )
new_class.add_to_class(
- 'MultipleObjectsReturned',
+ "MultipleObjectsReturned",
subclass_exception(
- 'MultipleObjectsReturned',
+ "MultipleObjectsReturned",
tuple(
- x.MultipleObjectsReturned for x in parents if hasattr(x, '_meta') and not x._meta.abstract
- ) or (MultipleObjectsReturned,),
+ x.MultipleObjectsReturned
+ for x in parents
+ if hasattr(x, "_meta") and not x._meta.abstract
+ )
+ or (MultipleObjectsReturned,),
module,
- attached_to=new_class))
+ attached_to=new_class,
+ ),
+ )
if base_meta and not base_meta.abstract:
# Non-abstract child classes inherit some attributes from their
# non-abstract parent (unless an ABC comes before it in the
# method resolution order).
- if not hasattr(meta, 'ordering'):
+ if not hasattr(meta, "ordering"):
new_class._meta.ordering = base_meta.ordering
- if not hasattr(meta, 'get_latest_by'):
+ if not hasattr(meta, "get_latest_by"):
new_class._meta.get_latest_by = base_meta.get_latest_by
is_proxy = new_class._meta.proxy
@@ -153,7 +182,9 @@ class ModelBase(type):
# If the model is a proxy, ensure that the base class
# hasn't been swapped out.
if is_proxy and base_meta and base_meta.swapped:
- raise TypeError("%s cannot proxy the swapped model '%s'." % (name, base_meta.swapped))
+ raise TypeError(
+ "%s cannot proxy the swapped model '%s'." % (name, base_meta.swapped)
+ )
# Add remaining attributes (those with a contribute_to_class() method)
# to the class.
@@ -164,14 +195,14 @@ class ModelBase(type):
new_fields = chain(
new_class._meta.local_fields,
new_class._meta.local_many_to_many,
- new_class._meta.private_fields
+ new_class._meta.private_fields,
)
field_names = {f.name for f in new_fields}
# Basic setup for proxy models.
if is_proxy:
base = None
- for parent in [kls for kls in parents if hasattr(kls, '_meta')]:
+ for parent in [kls for kls in parents if hasattr(kls, "_meta")]:
if parent._meta.abstract:
if parent._meta.fields:
raise TypeError(
@@ -183,9 +214,14 @@ class ModelBase(type):
if base is None:
base = parent
elif parent._meta.concrete_model is not base._meta.concrete_model:
- raise TypeError("Proxy model '%s' has more than one non-abstract model base class." % name)
+ raise TypeError(
+ "Proxy model '%s' has more than one non-abstract model base class."
+ % name
+ )
if base is None:
- raise TypeError("Proxy model '%s' has no non-abstract model base class." % name)
+ raise TypeError(
+ "Proxy model '%s' has no non-abstract model base class." % name
+ )
new_class._meta.setup_proxy(base)
new_class._meta.concrete_model = base._meta.concrete_model
else:
@@ -195,7 +231,7 @@ class ModelBase(type):
parent_links = {}
for base in reversed([new_class] + parents):
# Conceptually equivalent to `if base is Model`.
- if not hasattr(base, '_meta'):
+ if not hasattr(base, "_meta"):
continue
# Skip concrete parent classes.
if base != new_class and not base._meta.abstract:
@@ -210,7 +246,7 @@ class ModelBase(type):
inherited_attributes = set()
# Do the appropriate setup for any model parents.
for base in new_class.mro():
- if base not in parents or not hasattr(base, '_meta'):
+ if base not in parents or not hasattr(base, "_meta"):
# Things without _meta aren't functional models, so they're
# uninteresting parents.
inherited_attributes.update(base.__dict__)
@@ -223,8 +259,9 @@ class ModelBase(type):
for field in parent_fields:
if field.name in field_names:
raise FieldError(
- 'Local field %r in class %r clashes with field of '
- 'the same name from base class %r.' % (
+ "Local field %r in class %r clashes with field of "
+ "the same name from base class %r."
+ % (
field.name,
name,
base.__name__,
@@ -239,7 +276,7 @@ class ModelBase(type):
if base_key in parent_links:
field = parent_links[base_key]
elif not is_proxy:
- attr_name = '%s_ptr' % base._meta.model_name
+ attr_name = "%s_ptr" % base._meta.model_name
field = OneToOneField(
base,
on_delete=CASCADE,
@@ -252,7 +289,8 @@ class ModelBase(type):
raise FieldError(
"Auto-generated field '%s' in class %r for "
"parent_link to base class %r clashes with "
- "declared field of the same name." % (
+ "declared field of the same name."
+ % (
attr_name,
name,
base.__name__,
@@ -271,9 +309,11 @@ class ModelBase(type):
# Add fields from abstract base class if it wasn't overridden.
for field in parent_fields:
- if (field.name not in field_names and
- field.name not in new_class.__dict__ and
- field.name not in inherited_attributes):
+ if (
+ field.name not in field_names
+ and field.name not in new_class.__dict__
+ and field.name not in inherited_attributes
+ ):
new_field = copy.deepcopy(field)
new_class.add_to_class(field.name, new_field)
# Replace parent links defined on this base by the new
@@ -292,8 +332,9 @@ class ModelBase(type):
if field.name in field_names:
if not base._meta.abstract:
raise FieldError(
- 'Local field %r in class %r clashes with field of '
- 'the same name from base class %r.' % (
+ "Local field %r in class %r clashes with field of "
+ "the same name from base class %r."
+ % (
field.name,
name,
base.__name__,
@@ -307,7 +348,9 @@ class ModelBase(type):
# Copy indexes so that index names are unique when models extend an
# abstract model.
- new_class._meta.indexes = [copy.deepcopy(idx) for idx in new_class._meta.indexes]
+ new_class._meta.indexes = [
+ copy.deepcopy(idx) for idx in new_class._meta.indexes
+ ]
if abstract:
# Abstract base models can't be instantiated and don't appear in
@@ -333,8 +376,12 @@ class ModelBase(type):
opts._prepare(cls)
if opts.order_with_respect_to:
- cls.get_next_in_order = partialmethod(cls._get_next_or_previous_in_order, is_next=True)
- cls.get_previous_in_order = partialmethod(cls._get_next_or_previous_in_order, is_next=False)
+ cls.get_next_in_order = partialmethod(
+ cls._get_next_or_previous_in_order, is_next=True
+ )
+ cls.get_previous_in_order = partialmethod(
+ cls._get_next_or_previous_in_order, is_next=False
+ )
# Defer creating accessors on the foreign class until it has been
# created and registered. If remote_field is None, we're ordering
@@ -348,21 +395,26 @@ class ModelBase(type):
# Give the class a docstring -- its definition.
if cls.__doc__ is None:
- cls.__doc__ = "%s(%s)" % (cls.__name__, ", ".join(f.name for f in opts.fields))
+ cls.__doc__ = "%s(%s)" % (
+ cls.__name__,
+ ", ".join(f.name for f in opts.fields),
+ )
- get_absolute_url_override = settings.ABSOLUTE_URL_OVERRIDES.get(opts.label_lower)
+ get_absolute_url_override = settings.ABSOLUTE_URL_OVERRIDES.get(
+ opts.label_lower
+ )
if get_absolute_url_override:
- setattr(cls, 'get_absolute_url', get_absolute_url_override)
+ setattr(cls, "get_absolute_url", get_absolute_url_override)
if not opts.managers:
- if any(f.name == 'objects' for f in opts.fields):
+ if any(f.name == "objects" for f in opts.fields):
raise ValueError(
"Model %s must specify a custom Manager, because it has a "
"field named 'objects'." % cls.__name__
)
manager = Manager()
manager.auto_created = True
- cls.add_to_class('objects', manager)
+ cls.add_to_class("objects", manager)
# Set the name of _meta.indexes. This can't be done in
# Options.contribute_to_class() because fields haven't been added to
@@ -399,6 +451,7 @@ class ModelStateCacheDescriptor:
class ModelState:
"""Store model instance state."""
+
db = None
# If true, uniqueness validation checks will consider this a new, unsaved
# object. Necessary for correct validation of new instances of objects with
@@ -410,19 +463,18 @@ class ModelState:
def __getstate__(self):
state = self.__dict__.copy()
- if 'fields_cache' in state:
- state['fields_cache'] = self.fields_cache.copy()
+ if "fields_cache" in state:
+ state["fields_cache"] = self.fields_cache.copy()
# Manager instances stored in related_managers_cache won't necessarily
# be deserializable if they were dynamically created via an inner
# scope, e.g. create_forward_many_to_many_manager() and
# create_generic_related_manager().
- if 'related_managers_cache' in state:
- state['related_managers_cache'] = {}
+ if "related_managers_cache" in state:
+ state["related_managers_cache"] = {}
return state
class Model(metaclass=ModelBase):
-
def __init__(self, *args, **kwargs):
# Alias some things as locals to avoid repeat global lookups
cls = self.__class__
@@ -430,7 +482,7 @@ class Model(metaclass=ModelBase):
_setattr = setattr
_DEFERRED = DEFERRED
if opts.abstract:
- raise TypeError('Abstract models cannot be instantiated.')
+ raise TypeError("Abstract models cannot be instantiated.")
pre_init.send(sender=cls, args=args, kwargs=kwargs)
@@ -529,10 +581,10 @@ class Model(metaclass=ModelBase):
if value is not _DEFERRED:
_setattr(self, prop, value)
if unexpected:
- unexpected_names = ', '.join(repr(n) for n in unexpected)
+ unexpected_names = ", ".join(repr(n) for n in unexpected)
raise TypeError(
- f'{cls.__name__}() got unexpected keyword arguments: '
- f'{unexpected_names}'
+ f"{cls.__name__}() got unexpected keyword arguments: "
+ f"{unexpected_names}"
)
super().__init__()
post_init.send(sender=cls, instance=self)
@@ -551,10 +603,10 @@ class Model(metaclass=ModelBase):
return new
def __repr__(self):
- return '<%s: %s>' % (self.__class__.__name__, self)
+ return "<%s: %s>" % (self.__class__.__name__, self)
def __str__(self):
- return '%s object (%s)' % (self.__class__.__name__, self.pk)
+ return "%s object (%s)" % (self.__class__.__name__, self.pk)
def __eq__(self, other):
if not isinstance(other, Model):
@@ -580,7 +632,7 @@ class Model(metaclass=ModelBase):
def __getstate__(self):
"""Hook to allow choosing the attributes to pickle."""
state = self.__dict__.copy()
- state['_state'] = copy.copy(state['_state'])
+ state["_state"] = copy.copy(state["_state"])
# memoryview cannot be pickled, so cast it to bytes and store
# separately.
_memoryview_attrs = []
@@ -588,7 +640,7 @@ class Model(metaclass=ModelBase):
if isinstance(value, memoryview):
_memoryview_attrs.append((attr, bytes(value)))
if _memoryview_attrs:
- state['_memoryview_attrs'] = _memoryview_attrs
+ state["_memoryview_attrs"] = _memoryview_attrs
for attr, value in _memoryview_attrs:
state.pop(attr)
return state
@@ -610,8 +662,8 @@ class Model(metaclass=ModelBase):
RuntimeWarning,
stacklevel=2,
)
- if '_memoryview_attrs' in state:
- for attr, value in state.pop('_memoryview_attrs'):
+ if "_memoryview_attrs" in state:
+ for attr, value in state.pop("_memoryview_attrs"):
state[attr] = memoryview(value)
self.__dict__.update(state)
@@ -632,7 +684,8 @@ class Model(metaclass=ModelBase):
Return a set containing names of deferred fields for this instance.
"""
return {
- f.attname for f in self._meta.concrete_fields
+ f.attname
+ for f in self._meta.concrete_fields
if f.attname not in self.__dict__
}
@@ -654,7 +707,7 @@ class Model(metaclass=ModelBase):
if fields is None:
self._prefetched_objects_cache = {}
else:
- prefetched_objects_cache = getattr(self, '_prefetched_objects_cache', ())
+ prefetched_objects_cache = getattr(self, "_prefetched_objects_cache", ())
for field in fields:
if field in prefetched_objects_cache:
del prefetched_objects_cache[field]
@@ -664,10 +717,13 @@ class Model(metaclass=ModelBase):
if any(LOOKUP_SEP in f for f in fields):
raise ValueError(
'Found "%s" in fields argument. Relations and transforms '
- 'are not allowed in fields.' % LOOKUP_SEP)
+ "are not allowed in fields." % LOOKUP_SEP
+ )
- hints = {'instance': self}
- db_instance_qs = self.__class__._base_manager.db_manager(using, hints=hints).filter(pk=self.pk)
+ hints = {"instance": self}
+ db_instance_qs = self.__class__._base_manager.db_manager(
+ using, hints=hints
+ ).filter(pk=self.pk)
# Use provided fields, if not set then reload all non-deferred fields.
deferred_fields = self.get_deferred_fields()
@@ -675,8 +731,11 @@ class Model(metaclass=ModelBase):
fields = list(fields)
db_instance_qs = db_instance_qs.only(*fields)
elif deferred_fields:
- fields = [f.attname for f in self._meta.concrete_fields
- if f.attname not in deferred_fields]
+ fields = [
+ f.attname
+ for f in self._meta.concrete_fields
+ if f.attname not in deferred_fields
+ ]
db_instance_qs = db_instance_qs.only(*fields)
db_instance = db_instance_qs.get()
@@ -714,8 +773,9 @@ class Model(metaclass=ModelBase):
return getattr(self, field_name)
return getattr(self, field.attname)
- def save(self, force_insert=False, force_update=False, using=None,
- update_fields=None):
+ def save(
+ self, force_insert=False, force_update=False, using=None, update_fields=None
+ ):
"""
Save the current instance. Override this in a subclass if you want to
control the saving process.
@@ -724,7 +784,7 @@ class Model(metaclass=ModelBase):
that the "save" must be an SQL insert or update (or equivalent for
non-SQL backends), respectively. Normally, they should not be set.
"""
- self._prepare_related_fields_for_save(operation_name='save')
+ self._prepare_related_fields_for_save(operation_name="save")
using = using or router.db_for_write(self.__class__, instance=self)
if force_insert and (force_update or update_fields):
@@ -752,9 +812,9 @@ class Model(metaclass=ModelBase):
if non_model_fields:
raise ValueError(
- 'The following fields do not exist in this model, are m2m '
- 'fields, or are non-concrete fields: %s'
- % ', '.join(non_model_fields)
+ "The following fields do not exist in this model, are m2m "
+ "fields, or are non-concrete fields: %s"
+ % ", ".join(non_model_fields)
)
# If saving to the same database, and this model is deferred, then
@@ -762,18 +822,29 @@ class Model(metaclass=ModelBase):
elif not force_insert and deferred_fields and using == self._state.db:
field_names = set()
for field in self._meta.concrete_fields:
- if not field.primary_key and not hasattr(field, 'through'):
+ if not field.primary_key and not hasattr(field, "through"):
field_names.add(field.attname)
loaded_fields = field_names.difference(deferred_fields)
if loaded_fields:
update_fields = frozenset(loaded_fields)
- self.save_base(using=using, force_insert=force_insert,
- force_update=force_update, update_fields=update_fields)
+ self.save_base(
+ using=using,
+ force_insert=force_insert,
+ force_update=force_update,
+ update_fields=update_fields,
+ )
+
save.alters_data = True
- def save_base(self, raw=False, force_insert=False,
- force_update=False, using=None, update_fields=None):
+ def save_base(
+ self,
+ raw=False,
+ force_insert=False,
+ force_update=False,
+ using=None,
+ update_fields=None,
+ ):
"""
Handle the parts of saving which should be done only once per save,
yet need to be done in raw saves, too. This includes some sanity
@@ -793,7 +864,10 @@ class Model(metaclass=ModelBase):
meta = cls._meta
if not meta.auto_created:
pre_save.send(
- sender=origin, instance=self, raw=raw, using=using,
+ sender=origin,
+ instance=self,
+ raw=raw,
+ using=using,
update_fields=update_fields,
)
# A transaction isn't needed if one query is issued.
@@ -806,8 +880,12 @@ class Model(metaclass=ModelBase):
if not raw:
parent_inserted = self._save_parents(cls, using, update_fields)
updated = self._save_table(
- raw, cls, force_insert or parent_inserted,
- force_update, using, update_fields,
+ raw,
+ cls,
+ force_insert or parent_inserted,
+ force_update,
+ using,
+ update_fields,
)
# Store the database on which the object was saved
self._state.db = using
@@ -817,8 +895,12 @@ class Model(metaclass=ModelBase):
# Signal that the save is complete
if not meta.auto_created:
post_save.send(
- sender=origin, instance=self, created=(not updated),
- update_fields=update_fields, raw=raw, using=using,
+ sender=origin,
+ instance=self,
+ created=(not updated),
+ update_fields=update_fields,
+ raw=raw,
+ using=using,
)
save_base.alters_data = True
@@ -829,12 +911,19 @@ class Model(metaclass=ModelBase):
inserted = False
for parent, field in meta.parents.items():
# Make sure the link fields are synced between parent and self.
- if (field and getattr(self, parent._meta.pk.attname) is None and
- getattr(self, field.attname) is not None):
+ if (
+ field
+ and getattr(self, parent._meta.pk.attname) is None
+ and getattr(self, field.attname) is not None
+ ):
setattr(self, parent._meta.pk.attname, getattr(self, field.attname))
- parent_inserted = self._save_parents(cls=parent, using=using, update_fields=update_fields)
+ parent_inserted = self._save_parents(
+ cls=parent, using=using, update_fields=update_fields
+ )
updated = self._save_table(
- cls=parent, using=using, update_fields=update_fields,
+ cls=parent,
+ using=using,
+ update_fields=update_fields,
force_insert=parent_inserted,
)
if not updated:
@@ -851,8 +940,15 @@ class Model(metaclass=ModelBase):
field.delete_cached_value(self)
return inserted
- def _save_table(self, raw=False, cls=None, force_insert=False,
- force_update=False, using=None, update_fields=None):
+ def _save_table(
+ self,
+ raw=False,
+ cls=None,
+ force_insert=False,
+ force_update=False,
+ using=None,
+ update_fields=None,
+ ):
"""
Do the heavy-lifting involved in saving. Update or insert the data
for a single table.
@@ -861,8 +957,11 @@ class Model(metaclass=ModelBase):
non_pks = [f for f in meta.local_concrete_fields if not f.primary_key]
if update_fields:
- non_pks = [f for f in non_pks
- if f.name in update_fields or f.attname in update_fields]
+ non_pks = [
+ f
+ for f in non_pks
+ if f.name in update_fields or f.attname in update_fields
+ ]
pk_val = self._get_pk_val(meta)
if pk_val is None:
@@ -874,21 +973,28 @@ class Model(metaclass=ModelBase):
updated = False
# Skip an UPDATE when adding an instance and primary key has a default.
if (
- not raw and
- not force_insert and
- self._state.adding and
- meta.pk.default and
- meta.pk.default is not NOT_PROVIDED
+ not raw
+ and not force_insert
+ and self._state.adding
+ and meta.pk.default
+ and meta.pk.default is not NOT_PROVIDED
):
force_insert = True
# If possible, try an UPDATE. If that doesn't update anything, do an INSERT.
if pk_set and not force_insert:
base_qs = cls._base_manager.using(using)
- values = [(f, None, (getattr(self, f.attname) if raw else f.pre_save(self, False)))
- for f in non_pks]
+ values = [
+ (
+ f,
+ None,
+ (getattr(self, f.attname) if raw else f.pre_save(self, False)),
+ )
+ for f in non_pks
+ ]
forced_update = update_fields or force_update
- updated = self._do_update(base_qs, using, pk_val, values, update_fields,
- forced_update)
+ updated = self._do_update(
+ base_qs, using, pk_val, values, update_fields, forced_update
+ )
if force_update and not updated:
raise DatabaseError("Forced update did not affect any rows.")
if update_fields and not updated:
@@ -899,18 +1005,26 @@ class Model(metaclass=ModelBase):
# autopopulate the _order field
field = meta.order_with_respect_to
filter_args = field.get_filter_kwargs_for_object(self)
- self._order = cls._base_manager.using(using).filter(**filter_args).aggregate(
- _order__max=Coalesce(
- ExpressionWrapper(Max('_order') + Value(1), output_field=IntegerField()),
- Value(0),
- ),
- )['_order__max']
+ self._order = (
+ cls._base_manager.using(using)
+ .filter(**filter_args)
+ .aggregate(
+ _order__max=Coalesce(
+ ExpressionWrapper(
+ Max("_order") + Value(1), output_field=IntegerField()
+ ),
+ Value(0),
+ ),
+ )["_order__max"]
+ )
fields = meta.local_concrete_fields
if not pk_set:
fields = [f for f in fields if f is not meta.auto_field]
returning_fields = meta.db_returning_fields
- results = self._do_insert(cls._base_manager, using, fields, returning_fields, raw)
+ results = self._do_insert(
+ cls._base_manager, using, fields, returning_fields, raw
+ )
if results:
for value, field in zip(results[0], returning_fields):
setattr(self, field.attname, value)
@@ -931,7 +1045,8 @@ class Model(metaclass=ModelBase):
return update_fields is not None or filtered.exists()
if self._meta.select_on_save and not forced_update:
return (
- filtered.exists() and
+ filtered.exists()
+ and
# It may happen that the object is deleted from the DB right after
# this check, causing the subsequent UPDATE to return zero matching
# rows. The same result can occur in some rare cases when the
@@ -949,8 +1064,11 @@ class Model(metaclass=ModelBase):
return the newly created data for the model.
"""
return manager._insert(
- [self], fields=fields, returning_fields=returning_fields,
- using=using, raw=raw,
+ [self],
+ fields=fields,
+ returning_fields=returning_fields,
+ using=using,
+ raw=raw,
)
def _prepare_related_fields_for_save(self, operation_name, fields=None):
@@ -986,7 +1104,9 @@ class Model(metaclass=ModelBase):
setattr(self, field.attname, obj.pk)
# If the relationship's pk/to_field was changed, clear the
# cached relationship.
- if getattr(obj, field.target_field.attname) != getattr(self, field.attname):
+ if getattr(obj, field.target_field.attname) != getattr(
+ self, field.attname
+ ):
field.delete_cached_value(self)
def delete(self, using=None, keep_parents=False):
@@ -1006,42 +1126,59 @@ class Model(metaclass=ModelBase):
value = getattr(self, field.attname)
choices_dict = dict(make_hashable(field.flatchoices))
# force_str() to coerce lazy strings.
- return force_str(choices_dict.get(make_hashable(value), value), strings_only=True)
+ return force_str(
+ choices_dict.get(make_hashable(value), value), strings_only=True
+ )
def _get_next_or_previous_by_FIELD(self, field, is_next, **kwargs):
if not self.pk:
raise ValueError("get_next/get_previous cannot be used on unsaved objects.")
- op = 'gt' if is_next else 'lt'
- order = '' if is_next else '-'
+ op = "gt" if is_next else "lt"
+ order = "" if is_next else "-"
param = getattr(self, field.attname)
- q = Q((field.name, param), (f'pk__{op}', self.pk), _connector=Q.AND)
- q = Q(q, (f'{field.name}__{op}', param), _connector=Q.OR)
- qs = self.__class__._default_manager.using(self._state.db).filter(**kwargs).filter(q).order_by(
- '%s%s' % (order, field.name), '%spk' % order
+ q = Q((field.name, param), (f"pk__{op}", self.pk), _connector=Q.AND)
+ q = Q(q, (f"{field.name}__{op}", param), _connector=Q.OR)
+ qs = (
+ self.__class__._default_manager.using(self._state.db)
+ .filter(**kwargs)
+ .filter(q)
+ .order_by("%s%s" % (order, field.name), "%spk" % order)
)
try:
return qs[0]
except IndexError:
- raise self.DoesNotExist("%s matching query does not exist." % self.__class__._meta.object_name)
+ raise self.DoesNotExist(
+ "%s matching query does not exist." % self.__class__._meta.object_name
+ )
def _get_next_or_previous_in_order(self, is_next):
cachename = "__%s_order_cache" % is_next
if not hasattr(self, cachename):
- op = 'gt' if is_next else 'lt'
- order = '_order' if is_next else '-_order'
+ op = "gt" if is_next else "lt"
+ order = "_order" if is_next else "-_order"
order_field = self._meta.order_with_respect_to
filter_args = order_field.get_filter_kwargs_for_object(self)
- obj = self.__class__._default_manager.filter(**filter_args).filter(**{
- '_order__%s' % op: self.__class__._default_manager.values('_order').filter(**{
- self._meta.pk.name: self.pk
- })
- }).order_by(order)[:1].get()
+ obj = (
+ self.__class__._default_manager.filter(**filter_args)
+ .filter(
+ **{
+ "_order__%s"
+ % op: self.__class__._default_manager.values("_order").filter(
+ **{self._meta.pk.name: self.pk}
+ )
+ }
+ )
+ .order_by(order)[:1]
+ .get()
+ )
setattr(self, cachename, obj)
return getattr(self, cachename)
def prepare_database_save(self, field):
if self.pk is None:
- raise ValueError("Unsaved model instance %r cannot be used in an ORM query." % self)
+ raise ValueError(
+ "Unsaved model instance %r cannot be used in an ORM query." % self
+ )
return getattr(self, field.remote_field.get_related_field().attname)
def clean(self):
@@ -1085,7 +1222,9 @@ class Model(metaclass=ModelBase):
constraints = [(self.__class__, self._meta.total_unique_constraints)]
for parent_class in self._meta.get_parent_list():
if parent_class._meta.unique_together:
- unique_togethers.append((parent_class, parent_class._meta.unique_together))
+ unique_togethers.append(
+ (parent_class, parent_class._meta.unique_together)
+ )
if parent_class._meta.total_unique_constraints:
constraints.append(
(parent_class, parent_class._meta.total_unique_constraints)
@@ -1120,11 +1259,11 @@ class Model(metaclass=ModelBase):
if f.unique:
unique_checks.append((model_class, (name,)))
if f.unique_for_date and f.unique_for_date not in exclude:
- date_checks.append((model_class, 'date', name, f.unique_for_date))
+ date_checks.append((model_class, "date", name, f.unique_for_date))
if f.unique_for_year and f.unique_for_year not in exclude:
- date_checks.append((model_class, 'year', name, f.unique_for_year))
+ date_checks.append((model_class, "year", name, f.unique_for_year))
if f.unique_for_month and f.unique_for_month not in exclude:
- date_checks.append((model_class, 'month', name, f.unique_for_month))
+ date_checks.append((model_class, "month", name, f.unique_for_month))
return unique_checks, date_checks
def _perform_unique_checks(self, unique_checks):
@@ -1139,8 +1278,10 @@ class Model(metaclass=ModelBase):
f = self._meta.get_field(field_name)
lookup_value = getattr(self, f.attname)
# TODO: Handle multiple backends with different feature flags.
- if (lookup_value is None or
- (lookup_value == '' and connection.features.interprets_empty_strings_as_nulls)):
+ if lookup_value is None or (
+ lookup_value == ""
+ and connection.features.interprets_empty_strings_as_nulls
+ ):
# no value, skip the lookup
continue
if f.primary_key and not self._state.adding:
@@ -1168,7 +1309,9 @@ class Model(metaclass=ModelBase):
key = unique_check[0]
else:
key = NON_FIELD_ERRORS
- errors.setdefault(key, []).append(self.unique_error_message(model_class, unique_check))
+ errors.setdefault(key, []).append(
+ self.unique_error_message(model_class, unique_check)
+ )
return errors
@@ -1181,12 +1324,14 @@ class Model(metaclass=ModelBase):
date = getattr(self, unique_for)
if date is None:
continue
- if lookup_type == 'date':
- lookup_kwargs['%s__day' % unique_for] = date.day
- lookup_kwargs['%s__month' % unique_for] = date.month
- lookup_kwargs['%s__year' % unique_for] = date.year
+ if lookup_type == "date":
+ lookup_kwargs["%s__day" % unique_for] = date.day
+ lookup_kwargs["%s__month" % unique_for] = date.month
+ lookup_kwargs["%s__year" % unique_for] = date.year
else:
- lookup_kwargs['%s__%s' % (unique_for, lookup_type)] = getattr(date, lookup_type)
+ lookup_kwargs["%s__%s" % (unique_for, lookup_type)] = getattr(
+ date, lookup_type
+ )
lookup_kwargs[field] = getattr(self, field)
qs = model_class._default_manager.filter(**lookup_kwargs)
@@ -1205,46 +1350,48 @@ class Model(metaclass=ModelBase):
opts = self._meta
field = opts.get_field(field_name)
return ValidationError(
- message=field.error_messages['unique_for_date'],
- code='unique_for_date',
+ message=field.error_messages["unique_for_date"],
+ code="unique_for_date",
params={
- 'model': self,
- 'model_name': capfirst(opts.verbose_name),
- 'lookup_type': lookup_type,
- 'field': field_name,
- 'field_label': capfirst(field.verbose_name),
- 'date_field': unique_for,
- 'date_field_label': capfirst(opts.get_field(unique_for).verbose_name),
- }
+ "model": self,
+ "model_name": capfirst(opts.verbose_name),
+ "lookup_type": lookup_type,
+ "field": field_name,
+ "field_label": capfirst(field.verbose_name),
+ "date_field": unique_for,
+ "date_field_label": capfirst(opts.get_field(unique_for).verbose_name),
+ },
)
def unique_error_message(self, model_class, unique_check):
opts = model_class._meta
params = {
- 'model': self,
- 'model_class': model_class,
- 'model_name': capfirst(opts.verbose_name),
- 'unique_check': unique_check,
+ "model": self,
+ "model_class": model_class,
+ "model_name": capfirst(opts.verbose_name),
+ "unique_check": unique_check,
}
# A unique field
if len(unique_check) == 1:
field = opts.get_field(unique_check[0])
- params['field_label'] = capfirst(field.verbose_name)
+ params["field_label"] = capfirst(field.verbose_name)
return ValidationError(
- message=field.error_messages['unique'],
- code='unique',
+ message=field.error_messages["unique"],
+ code="unique",
params=params,
)
# unique_together
else:
- field_labels = [capfirst(opts.get_field(f).verbose_name) for f in unique_check]
- params['field_labels'] = get_text_list(field_labels, _('and'))
+ field_labels = [
+ capfirst(opts.get_field(f).verbose_name) for f in unique_check
+ ]
+ params["field_labels"] = get_text_list(field_labels, _("and"))
return ValidationError(
message=_("%(model_name)s with this %(field_labels)s already exists."),
- code='unique_together',
+ code="unique_together",
params=params,
)
@@ -1311,9 +1458,13 @@ class Model(metaclass=ModelBase):
@classmethod
def check(cls, **kwargs):
- errors = [*cls._check_swappable(), *cls._check_model(), *cls._check_managers(**kwargs)]
+ errors = [
+ *cls._check_swappable(),
+ *cls._check_model(),
+ *cls._check_managers(**kwargs),
+ ]
if not cls._meta.swapped:
- databases = kwargs.get('databases') or []
+ databases = kwargs.get("databases") or []
errors += [
*cls._check_fields(**kwargs),
*cls._check_m2m_through_same_relationship(),
@@ -1345,16 +1496,17 @@ class Model(metaclass=ModelBase):
@classmethod
def _check_default_pk(cls):
if (
- not cls._meta.abstract and
- cls._meta.pk.auto_created and
+ not cls._meta.abstract
+ and cls._meta.pk.auto_created
+ and
# Inherited PKs are checked in parents models.
not (
- isinstance(cls._meta.pk, OneToOneField) and
- cls._meta.pk.remote_field.parent_link
- ) and
- not settings.is_overridden('DEFAULT_AUTO_FIELD') and
- cls._meta.app_config and
- not cls._meta.app_config._is_default_auto_field_overridden
+ isinstance(cls._meta.pk, OneToOneField)
+ and cls._meta.pk.remote_field.parent_link
+ )
+ and not settings.is_overridden("DEFAULT_AUTO_FIELD")
+ and cls._meta.app_config
+ and not cls._meta.app_config._is_default_auto_field_overridden
):
return [
checks.Warning(
@@ -1368,7 +1520,7 @@ class Model(metaclass=ModelBase):
f"of AutoField, e.g. 'django.db.models.BigAutoField'."
),
obj=cls,
- id='models.W042',
+ id="models.W042",
),
]
return []
@@ -1383,19 +1535,19 @@ class Model(metaclass=ModelBase):
except ValueError:
errors.append(
checks.Error(
- "'%s' is not of the form 'app_label.app_name'." % cls._meta.swappable,
- id='models.E001',
+ "'%s' is not of the form 'app_label.app_name'."
+ % cls._meta.swappable,
+ id="models.E001",
)
)
except LookupError:
- app_label, model_name = cls._meta.swapped.split('.')
+ app_label, model_name = cls._meta.swapped.split(".")
errors.append(
checks.Error(
"'%s' references '%s.%s', which has not been "
- "installed, or is abstract." % (
- cls._meta.swappable, app_label, model_name
- ),
- id='models.E002',
+ "installed, or is abstract."
+ % (cls._meta.swappable, app_label, model_name),
+ id="models.E002",
)
)
return errors
@@ -1408,7 +1560,7 @@ class Model(metaclass=ModelBase):
errors.append(
checks.Error(
"Proxy model '%s' contains model fields." % cls.__name__,
- id='models.E017',
+ id="models.E017",
)
)
return errors
@@ -1433,8 +1585,7 @@ class Model(metaclass=ModelBase):
@classmethod
def _check_m2m_through_same_relationship(cls):
- """ Check if no relationship model is used by more than one m2m field.
- """
+ """Check if no relationship model is used by more than one m2m field."""
errors = []
seen_intermediary_signatures = []
@@ -1448,15 +1599,20 @@ class Model(metaclass=ModelBase):
fields = (f for f in fields if isinstance(f.remote_field.through, ModelBase))
for f in fields:
- signature = (f.remote_field.model, cls, f.remote_field.through, f.remote_field.through_fields)
+ signature = (
+ f.remote_field.model,
+ cls,
+ f.remote_field.through,
+ f.remote_field.through_fields,
+ )
if signature in seen_intermediary_signatures:
errors.append(
checks.Error(
"The model has two identical many-to-many relations "
- "through the intermediate model '%s'." %
- f.remote_field.through._meta.label,
+ "through the intermediate model '%s'."
+ % f.remote_field.through._meta.label,
obj=cls,
- id='models.E003',
+ id="models.E003",
)
)
else:
@@ -1466,15 +1622,17 @@ class Model(metaclass=ModelBase):
@classmethod
def _check_id_field(cls):
"""Check if `id` field is a primary key."""
- fields = [f for f in cls._meta.local_fields if f.name == 'id' and f != cls._meta.pk]
+ fields = [
+ f for f in cls._meta.local_fields if f.name == "id" and f != cls._meta.pk
+ ]
# fields is empty or consists of the invalid "id" field
- if fields and not fields[0].primary_key and cls._meta.pk.name == 'id':
+ if fields and not fields[0].primary_key and cls._meta.pk.name == "id":
return [
checks.Error(
"'id' can only be used as a field name if the field also "
"sets 'primary_key=True'.",
obj=cls,
- id='models.E004',
+ id="models.E004",
)
]
else:
@@ -1495,12 +1653,10 @@ class Model(metaclass=ModelBase):
checks.Error(
"The field '%s' from parent model "
"'%s' clashes with the field '%s' "
- "from parent model '%s'." % (
- clash.name, clash.model._meta,
- f.name, f.model._meta
- ),
+ "from parent model '%s'."
+ % (clash.name, clash.model._meta, f.name, f.model._meta),
obj=cls,
- id='models.E005',
+ id="models.E005",
)
)
used_fields[f.name] = f
@@ -1520,16 +1676,16 @@ class Model(metaclass=ModelBase):
# field "id" and automatically added unique field "id", both
# defined at the same model. This special case is considered in
# _check_id_field and here we ignore it.
- id_conflict = f.name == "id" and clash and clash.name == "id" and clash.model == cls
+ id_conflict = (
+ f.name == "id" and clash and clash.name == "id" and clash.model == cls
+ )
if clash and not id_conflict:
errors.append(
checks.Error(
"The field '%s' clashes with the field '%s' "
- "from model '%s'." % (
- f.name, clash.name, clash.model._meta
- ),
+ "from model '%s'." % (f.name, clash.name, clash.model._meta),
obj=f,
- id='models.E006',
+ id="models.E006",
)
)
used_fields[f.name] = f
@@ -1554,7 +1710,7 @@ class Model(metaclass=ModelBase):
"another field." % (f.name, column_name),
hint="Specify a 'db_column' for the field.",
obj=cls,
- id='models.E007'
+ id="models.E007",
)
)
else:
@@ -1566,13 +1722,13 @@ class Model(metaclass=ModelBase):
def _check_model_name_db_lookup_clashes(cls):
errors = []
model_name = cls.__name__
- if model_name.startswith('_') or model_name.endswith('_'):
+ if model_name.startswith("_") or model_name.endswith("_"):
errors.append(
checks.Error(
"The model name '%s' cannot start or end with an underscore "
"as it collides with the query lookup syntax." % model_name,
obj=cls,
- id='models.E023'
+ id="models.E023",
)
)
elif LOOKUP_SEP in model_name:
@@ -1581,7 +1737,7 @@ class Model(metaclass=ModelBase):
"The model name '%s' cannot contain double underscores as "
"it collides with the query lookup syntax." % model_name,
obj=cls,
- id='models.E024'
+ id="models.E024",
)
)
return errors
@@ -1591,7 +1747,8 @@ class Model(metaclass=ModelBase):
errors = []
property_names = cls._meta._property_names
related_field_accessors = (
- f.get_attname() for f in cls._meta._get_fields(reverse=False)
+ f.get_attname()
+ for f in cls._meta._get_fields(reverse=False)
if f.is_relation and f.related_model is not None
)
for accessor in related_field_accessors:
@@ -1601,7 +1758,7 @@ class Model(metaclass=ModelBase):
"The property '%s' clashes with a related field "
"accessor." % accessor,
obj=cls,
- id='models.E025',
+ id="models.E025",
)
)
return errors
@@ -1615,7 +1772,7 @@ class Model(metaclass=ModelBase):
"The model cannot have more than one field with "
"'primary_key=True'.",
obj=cls,
- id='models.E026',
+ id="models.E026",
)
)
return errors
@@ -1628,16 +1785,18 @@ class Model(metaclass=ModelBase):
checks.Error(
"'index_together' must be a list or tuple.",
obj=cls,
- id='models.E008',
+ id="models.E008",
)
]
- elif any(not isinstance(fields, (tuple, list)) for fields in cls._meta.index_together):
+ elif any(
+ not isinstance(fields, (tuple, list)) for fields in cls._meta.index_together
+ ):
return [
checks.Error(
"All 'index_together' elements must be lists or tuples.",
obj=cls,
- id='models.E009',
+ id="models.E009",
)
]
@@ -1655,16 +1814,19 @@ class Model(metaclass=ModelBase):
checks.Error(
"'unique_together' must be a list or tuple.",
obj=cls,
- id='models.E010',
+ id="models.E010",
)
]
- elif any(not isinstance(fields, (tuple, list)) for fields in cls._meta.unique_together):
+ elif any(
+ not isinstance(fields, (tuple, list))
+ for fields in cls._meta.unique_together
+ ):
return [
checks.Error(
"All 'unique_together' elements must be lists or tuples.",
obj=cls,
- id='models.E011',
+ id="models.E011",
)
]
@@ -1682,13 +1844,13 @@ class Model(metaclass=ModelBase):
for index in cls._meta.indexes:
# Index name can't start with an underscore or a number, restricted
# for cross-database compatibility with Oracle.
- if index.name[0] == '_' or index.name[0].isdigit():
+ if index.name[0] == "_" or index.name[0].isdigit():
errors.append(
checks.Error(
"The index name '%s' cannot start with an underscore "
"or a number." % index.name,
obj=cls,
- id='models.E033',
+ id="models.E033",
),
)
if len(index.name) > index.max_name_length:
@@ -1697,7 +1859,7 @@ class Model(metaclass=ModelBase):
"The index name '%s' cannot be longer than %d "
"characters." % (index.name, index.max_name_length),
obj=cls,
- id='models.E034',
+ id="models.E034",
),
)
if index.contains_expressions:
@@ -1710,57 +1872,59 @@ class Model(metaclass=ModelBase):
continue
connection = connections[db]
if not (
- connection.features.supports_partial_indexes or
- 'supports_partial_indexes' in cls._meta.required_db_features
+ connection.features.supports_partial_indexes
+ or "supports_partial_indexes" in cls._meta.required_db_features
) and any(index.condition is not None for index in cls._meta.indexes):
errors.append(
checks.Warning(
- '%s does not support indexes with conditions.'
+ "%s does not support indexes with conditions."
% connection.display_name,
hint=(
"Conditions will be ignored. Silence this warning "
"if you don't care about it."
),
obj=cls,
- id='models.W037',
+ id="models.W037",
)
)
if not (
- connection.features.supports_covering_indexes or
- 'supports_covering_indexes' in cls._meta.required_db_features
+ connection.features.supports_covering_indexes
+ or "supports_covering_indexes" in cls._meta.required_db_features
) and any(index.include for index in cls._meta.indexes):
errors.append(
checks.Warning(
- '%s does not support indexes with non-key columns.'
+ "%s does not support indexes with non-key columns."
% connection.display_name,
hint=(
"Non-key columns will be ignored. Silence this "
"warning if you don't care about it."
),
obj=cls,
- id='models.W040',
+ id="models.W040",
)
)
if not (
- connection.features.supports_expression_indexes or
- 'supports_expression_indexes' in cls._meta.required_db_features
+ connection.features.supports_expression_indexes
+ or "supports_expression_indexes" in cls._meta.required_db_features
) and any(index.contains_expressions for index in cls._meta.indexes):
errors.append(
checks.Warning(
- '%s does not support indexes on expressions.'
+ "%s does not support indexes on expressions."
% connection.display_name,
hint=(
"An index won't be created. Silence this warning "
"if you don't care about it."
),
obj=cls,
- id='models.W043',
+ id="models.W043",
)
)
- fields = [field for index in cls._meta.indexes for field, _ in index.fields_orders]
+ fields = [
+ field for index in cls._meta.indexes for field, _ in index.fields_orders
+ ]
fields += [include for index in cls._meta.indexes for include in index.include]
fields += references
- errors.extend(cls._check_local_fields(fields, 'indexes'))
+ errors.extend(cls._check_local_fields(fields, "indexes"))
return errors
@classmethod
@@ -1772,7 +1936,7 @@ class Model(metaclass=ModelBase):
forward_fields_map = {}
for field in cls._meta._get_fields(reverse=False):
forward_fields_map[field.name] = field
- if hasattr(field, 'attname'):
+ if hasattr(field, "attname"):
forward_fields_map[field.attname] = field
errors = []
@@ -1782,11 +1946,13 @@ class Model(metaclass=ModelBase):
except KeyError:
errors.append(
checks.Error(
- "'%s' refers to the nonexistent field '%s'." % (
- option, field_name,
+ "'%s' refers to the nonexistent field '%s'."
+ % (
+ option,
+ field_name,
),
obj=cls,
- id='models.E012',
+ id="models.E012",
)
)
else:
@@ -1794,11 +1960,14 @@ class Model(metaclass=ModelBase):
errors.append(
checks.Error(
"'%s' refers to a ManyToManyField '%s', but "
- "ManyToManyFields are not permitted in '%s'." % (
- option, field_name, option,
+ "ManyToManyFields are not permitted in '%s'."
+ % (
+ option,
+ field_name,
+ option,
),
obj=cls,
- id='models.E013',
+ id="models.E013",
)
)
elif field not in cls._meta.local_fields:
@@ -1808,7 +1977,7 @@ class Model(metaclass=ModelBase):
% (option, field_name, cls._meta.object_name),
hint="This issue may be caused by multi-table inheritance.",
obj=cls,
- id='models.E016',
+ id="models.E016",
)
)
return errors
@@ -1824,7 +1993,7 @@ class Model(metaclass=ModelBase):
checks.Error(
"'ordering' and 'order_with_respect_to' cannot be used together.",
obj=cls,
- id='models.E021',
+ id="models.E021",
),
]
@@ -1836,7 +2005,7 @@ class Model(metaclass=ModelBase):
checks.Error(
"'ordering' must be a tuple or list (even if you want to order by only one field).",
obj=cls,
- id='models.E014',
+ id="models.E014",
)
]
@@ -1844,10 +2013,10 @@ class Model(metaclass=ModelBase):
fields = cls._meta.ordering
# Skip expressions and '?' fields.
- fields = (f for f in fields if isinstance(f, str) and f != '?')
+ fields = (f for f in fields if isinstance(f, str) and f != "?")
# Convert "-field" to "field".
- fields = ((f[1:] if f.startswith('-') else f) for f in fields)
+ fields = ((f[1:] if f.startswith("-") else f) for f in fields)
# Separate related fields and non-related fields.
_fields = []
@@ -1866,7 +2035,7 @@ class Model(metaclass=ModelBase):
for part in field.split(LOOKUP_SEP):
try:
# pk is an alias that won't be found by opts.get_field.
- if part == 'pk':
+ if part == "pk":
fld = _cls._meta.pk
else:
fld = _cls._meta.get_field(part)
@@ -1883,13 +2052,13 @@ class Model(metaclass=ModelBase):
"'ordering' refers to the nonexistent field, "
"related field, or lookup '%s'." % field,
obj=cls,
- id='models.E015',
+ id="models.E015",
)
)
# Skip ordering on pk. This is always a valid order_by field
# but is an alias and therefore won't be found by opts.get_field.
- fields = {f for f in fields if f != 'pk'}
+ fields = {f for f in fields if f != "pk"}
# Check for invalid or nonexistent fields in ordering.
invalid_fields = []
@@ -1897,10 +2066,14 @@ class Model(metaclass=ModelBase):
# Any field name that is not present in field_names does not exist.
# Also, ordering by m2m fields is not allowed.
opts = cls._meta
- valid_fields = set(chain.from_iterable(
- (f.name, f.attname) if not (f.auto_created and not f.concrete) else (f.field.related_query_name(),)
- for f in chain(opts.fields, opts.related_objects)
- ))
+ valid_fields = set(
+ chain.from_iterable(
+ (f.name, f.attname)
+ if not (f.auto_created and not f.concrete)
+ else (f.field.related_query_name(),)
+ for f in chain(opts.fields, opts.related_objects)
+ )
+ )
invalid_fields.extend(fields - valid_fields)
@@ -1910,7 +2083,7 @@ class Model(metaclass=ModelBase):
"'ordering' refers to the nonexistent field, related "
"field, or lookup '%s'." % invalid_field,
obj=cls,
- id='models.E015',
+ id="models.E015",
)
)
return errors
@@ -1952,7 +2125,11 @@ class Model(metaclass=ModelBase):
# Check if auto-generated name for the field is too long
# for the database.
- if f.db_column is None and column_name is not None and len(column_name) > allowed_len:
+ if (
+ f.db_column is None
+ and column_name is not None
+ and len(column_name) > allowed_len
+ ):
errors.append(
checks.Error(
'Autogenerated column name too long for field "%s". '
@@ -1960,7 +2137,7 @@ class Model(metaclass=ModelBase):
% (column_name, allowed_len, db_alias),
hint="Set the column name manually using 'db_column'.",
obj=cls,
- id='models.E018',
+ id="models.E018",
)
)
@@ -1973,10 +2150,14 @@ class Model(metaclass=ModelBase):
# for the database.
for m2m in f.remote_field.through._meta.local_fields:
_, rel_name = m2m.get_attname_column()
- if m2m.db_column is None and rel_name is not None and len(rel_name) > allowed_len:
+ if (
+ m2m.db_column is None
+ and rel_name is not None
+ and len(rel_name) > allowed_len
+ ):
errors.append(
checks.Error(
- 'Autogenerated column name too long for M2M field '
+ "Autogenerated column name too long for M2M field "
'"%s". Maximum length is "%s" for database "%s".'
% (rel_name, allowed_len, db_alias),
hint=(
@@ -1984,7 +2165,7 @@ class Model(metaclass=ModelBase):
"M2M and then set column_name using 'db_column'."
),
obj=cls,
- id='models.E019',
+ id="models.E019",
)
)
@@ -2002,7 +2183,7 @@ class Model(metaclass=ModelBase):
yield from cls._get_expr_references(child)
elif isinstance(expr, F):
yield tuple(expr.name.split(LOOKUP_SEP))
- elif hasattr(expr, 'get_source_expressions'):
+ elif hasattr(expr, "get_source_expressions"):
for src_expr in expr.get_source_expressions():
yield from cls._get_expr_references(src_expr)
@@ -2014,132 +2195,145 @@ class Model(metaclass=ModelBase):
continue
connection = connections[db]
if not (
- connection.features.supports_table_check_constraints or
- 'supports_table_check_constraints' in cls._meta.required_db_features
+ connection.features.supports_table_check_constraints
+ or "supports_table_check_constraints" in cls._meta.required_db_features
) and any(
isinstance(constraint, CheckConstraint)
for constraint in cls._meta.constraints
):
errors.append(
checks.Warning(
- '%s does not support check constraints.' % connection.display_name,
+ "%s does not support check constraints."
+ % connection.display_name,
hint=(
"A constraint won't be created. Silence this "
"warning if you don't care about it."
),
obj=cls,
- id='models.W027',
+ id="models.W027",
)
)
if not (
- connection.features.supports_partial_indexes or
- 'supports_partial_indexes' in cls._meta.required_db_features
+ connection.features.supports_partial_indexes
+ or "supports_partial_indexes" in cls._meta.required_db_features
) and any(
- isinstance(constraint, UniqueConstraint) and constraint.condition is not None
+ isinstance(constraint, UniqueConstraint)
+ and constraint.condition is not None
for constraint in cls._meta.constraints
):
errors.append(
checks.Warning(
- '%s does not support unique constraints with '
- 'conditions.' % connection.display_name,
+ "%s does not support unique constraints with "
+ "conditions." % connection.display_name,
hint=(
"A constraint won't be created. Silence this "
"warning if you don't care about it."
),
obj=cls,
- id='models.W036',
+ id="models.W036",
)
)
if not (
- connection.features.supports_deferrable_unique_constraints or
- 'supports_deferrable_unique_constraints' in cls._meta.required_db_features
+ connection.features.supports_deferrable_unique_constraints
+ or "supports_deferrable_unique_constraints"
+ in cls._meta.required_db_features
) and any(
- isinstance(constraint, UniqueConstraint) and constraint.deferrable is not None
+ isinstance(constraint, UniqueConstraint)
+ and constraint.deferrable is not None
for constraint in cls._meta.constraints
):
errors.append(
checks.Warning(
- '%s does not support deferrable unique constraints.'
+ "%s does not support deferrable unique constraints."
% connection.display_name,
hint=(
"A constraint won't be created. Silence this "
"warning if you don't care about it."
),
obj=cls,
- id='models.W038',
+ id="models.W038",
)
)
if not (
- connection.features.supports_covering_indexes or
- 'supports_covering_indexes' in cls._meta.required_db_features
+ connection.features.supports_covering_indexes
+ or "supports_covering_indexes" in cls._meta.required_db_features
) and any(
isinstance(constraint, UniqueConstraint) and constraint.include
for constraint in cls._meta.constraints
):
errors.append(
checks.Warning(
- '%s does not support unique constraints with non-key '
- 'columns.' % connection.display_name,
+ "%s does not support unique constraints with non-key "
+ "columns." % connection.display_name,
hint=(
"A constraint won't be created. Silence this "
"warning if you don't care about it."
),
obj=cls,
- id='models.W039',
+ id="models.W039",
)
)
if not (
- connection.features.supports_expression_indexes or
- 'supports_expression_indexes' in cls._meta.required_db_features
+ connection.features.supports_expression_indexes
+ or "supports_expression_indexes" in cls._meta.required_db_features
) and any(
- isinstance(constraint, UniqueConstraint) and constraint.contains_expressions
+ isinstance(constraint, UniqueConstraint)
+ and constraint.contains_expressions
for constraint in cls._meta.constraints
):
errors.append(
checks.Warning(
- '%s does not support unique constraints on '
- 'expressions.' % connection.display_name,
+ "%s does not support unique constraints on "
+ "expressions." % connection.display_name,
hint=(
"A constraint won't be created. Silence this "
"warning if you don't care about it."
),
obj=cls,
- id='models.W044',
+ id="models.W044",
)
)
- fields = set(chain.from_iterable(
- (*constraint.fields, *constraint.include)
- for constraint in cls._meta.constraints if isinstance(constraint, UniqueConstraint)
- ))
+ fields = set(
+ chain.from_iterable(
+ (*constraint.fields, *constraint.include)
+ for constraint in cls._meta.constraints
+ if isinstance(constraint, UniqueConstraint)
+ )
+ )
references = set()
for constraint in cls._meta.constraints:
if isinstance(constraint, UniqueConstraint):
if (
- connection.features.supports_partial_indexes or
- 'supports_partial_indexes' not in cls._meta.required_db_features
+ connection.features.supports_partial_indexes
+ or "supports_partial_indexes"
+ not in cls._meta.required_db_features
) and isinstance(constraint.condition, Q):
- references.update(cls._get_expr_references(constraint.condition))
+ references.update(
+ cls._get_expr_references(constraint.condition)
+ )
if (
- connection.features.supports_expression_indexes or
- 'supports_expression_indexes' not in cls._meta.required_db_features
+ connection.features.supports_expression_indexes
+ or "supports_expression_indexes"
+ not in cls._meta.required_db_features
) and constraint.contains_expressions:
for expression in constraint.expressions:
references.update(cls._get_expr_references(expression))
elif isinstance(constraint, CheckConstraint):
if (
- connection.features.supports_table_check_constraints or
- 'supports_table_check_constraints' not in cls._meta.required_db_features
+ connection.features.supports_table_check_constraints
+ or "supports_table_check_constraints"
+ not in cls._meta.required_db_features
) and isinstance(constraint.check, Q):
references.update(cls._get_expr_references(constraint.check))
for field_name, *lookups in references:
# pk is an alias that won't be found by opts.get_field.
- if field_name != 'pk':
+ if field_name != "pk":
fields.add(field_name)
if not lookups:
# If it has no lookups it cannot result in a JOIN.
continue
try:
- if field_name == 'pk':
+ if field_name == "pk":
field = cls._meta.pk
else:
field = cls._meta.get_field(field_name)
@@ -2150,20 +2344,20 @@ class Model(metaclass=ModelBase):
# JOIN must happen at the first lookup.
first_lookup = lookups[0]
if (
- hasattr(field, 'get_transform') and
- hasattr(field, 'get_lookup') and
- field.get_transform(first_lookup) is None and
- field.get_lookup(first_lookup) is None
+ hasattr(field, "get_transform")
+ and hasattr(field, "get_lookup")
+ and field.get_transform(first_lookup) is None
+ and field.get_lookup(first_lookup) is None
):
errors.append(
checks.Error(
"'constraints' refers to the joined field '%s'."
% LOOKUP_SEP.join([field_name] + lookups),
obj=cls,
- id='models.E041',
+ id="models.E041",
)
)
- errors.extend(cls._check_local_fields(fields, 'constraints'))
+ errors.extend(cls._check_local_fields(fields, "constraints"))
return errors
@@ -2173,14 +2367,16 @@ class Model(metaclass=ModelBase):
# ORDERING METHODS #########################
+
def method_set_order(self, ordered_obj, id_list, using=None):
if using is None:
using = DEFAULT_DB_ALIAS
order_wrt = ordered_obj._meta.order_with_respect_to
filter_args = order_wrt.get_forward_related_filter(self)
- ordered_obj.objects.db_manager(using).filter(**filter_args).bulk_update([
- ordered_obj(pk=pk, _order=order) for order, pk in enumerate(id_list)
- ], ['_order'])
+ ordered_obj.objects.db_manager(using).filter(**filter_args).bulk_update(
+ [ordered_obj(pk=pk, _order=order) for order, pk in enumerate(id_list)],
+ ["_order"],
+ )
def method_get_order(self, ordered_obj):
@@ -2193,15 +2389,16 @@ def method_get_order(self, ordered_obj):
def make_foreign_order_accessors(model, related_model):
setattr(
related_model,
- 'get_%s_order' % model.__name__.lower(),
- partialmethod(method_get_order, model)
+ "get_%s_order" % model.__name__.lower(),
+ partialmethod(method_get_order, model),
)
setattr(
related_model,
- 'set_%s_order' % model.__name__.lower(),
- partialmethod(method_set_order, model)
+ "set_%s_order" % model.__name__.lower(),
+ partialmethod(method_set_order, model),
)
+
########
# MISC #
########