Plain is headed towards 1.0! Subscribe for development updates →

plain.models

Model your data and store it in a database.

# app/users/models.py
from plain import models
from plain.passwords.models import PasswordField


class User(models.Model):
    email = models.EmailField(unique=True)
    password = PasswordField()
    is_staff = models.BooleanField(default=False)
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.email

Create, update, and delete instances of your models:

from .models import User


# Create a new user
user = User.objects.create(
    email="[email protected]",
    password="password",
)

# Update a user
user.email = "[email protected]"
user.save()

# Delete a user
user.delete()

# Query for users
staff_users = User.objects.filter(is_staff=True)

Installation

# app/settings.py
INSTALLED_PACKAGES = [
    ...
    "plain.models",
]

To connect to a database, you can provide a DATABASE_URL environment variable.

DATABASE_URL=postgresql://user:password@localhost:5432/dbname

Or you can manually define the DATABASES setting.

# app/settings.py
DATABASES = {
    "default": {
        "ENGINE": "plain.models.backends.postgresql",
        "NAME": "dbname",
        "USER": "user",
        "PASSWORD": "password",
        "HOST": "localhost",
        "PORT": "5432",
    }
}

Multiple backends are supported, including Postgres, MySQL, and SQLite.

Querying

Migrations

Migration docs

Fields

Field docs

Validation

Indexes and constraints

Managers

Forms

   1import copy
   2import inspect
   3import warnings
   4from functools import partialmethod
   5from itertools import chain
   6
   7import plain.runtime
   8from plain import preflight
   9from plain.exceptions import (
  10    NON_FIELD_ERRORS,
  11    FieldDoesNotExist,
  12    FieldError,
  13    MultipleObjectsReturned,
  14    ObjectDoesNotExist,
  15    ValidationError,
  16)
  17from plain.models import transaction
  18from plain.models.aggregates import Max
  19from plain.models.constants import LOOKUP_SEP
  20from plain.models.constraints import CheckConstraint, UniqueConstraint
  21from plain.models.db import (
  22    PLAIN_VERSION_PICKLE_KEY,
  23    DatabaseError,
  24    connection,
  25    connections,
  26    router,
  27)
  28from plain.models.deletion import CASCADE, Collector
  29from plain.models.expressions import ExpressionWrapper, RawSQL, Value
  30from plain.models.fields import NOT_PROVIDED, IntegerField
  31from plain.models.fields.related import (
  32    ForeignObjectRel,
  33    OneToOneField,
  34    lazy_related_operation,
  35    resolve_relation,
  36)
  37from plain.models.functions import Coalesce
  38from plain.models.manager import Manager
  39from plain.models.options import Options
  40from plain.models.query import F, Q
  41from plain.models.signals import (
  42    class_prepared,
  43    post_init,
  44    post_save,
  45    pre_init,
  46    pre_save,
  47)
  48from plain.models.utils import AltersData, make_model_tuple
  49from plain.packages import packages
  50from plain.utils.encoding import force_str
  51from plain.utils.hashable import make_hashable
  52
  53
  54class Deferred:
  55    def __repr__(self):
  56        return "<Deferred field>"
  57
  58    def __str__(self):
  59        return "<Deferred field>"
  60
  61
  62DEFERRED = Deferred()
  63
  64
  65def subclass_exception(name, bases, module, attached_to):
  66    """
  67    Create exception subclass. Used by ModelBase below.
  68
  69    The exception is created in a way that allows it to be pickled, assuming
  70    that the returned exception class will be added as an attribute to the
  71    'attached_to' class.
  72    """
  73    return type(
  74        name,
  75        bases,
  76        {
  77            "__module__": module,
  78            "__qualname__": f"{attached_to.__qualname__}.{name}",
  79        },
  80    )
  81
  82
  83def _has_contribute_to_class(value):
  84    # Only call contribute_to_class() if it's bound.
  85    return not inspect.isclass(value) and hasattr(value, "contribute_to_class")
  86
  87
  88class ModelBase(type):
  89    """Metaclass for all models."""
  90
  91    def __new__(cls, name, bases, attrs, **kwargs):
  92        super_new = super().__new__
  93
  94        # Also ensure initialization is only performed for subclasses of Model
  95        # (excluding Model class itself).
  96        parents = [b for b in bases if isinstance(b, ModelBase)]
  97        if not parents:
  98            return super_new(cls, name, bases, attrs)
  99
 100        # Create the class.
 101        module = attrs.pop("__module__")
 102        new_attrs = {"__module__": module}
 103        classcell = attrs.pop("__classcell__", None)
 104        if classcell is not None:
 105            new_attrs["__classcell__"] = classcell
 106        attr_meta = attrs.pop("Meta", None)
 107        # Pass all attrs without a (Plain-specific) contribute_to_class()
 108        # method to type.__new__() so that they're properly initialized
 109        # (i.e. __set_name__()).
 110        contributable_attrs = {}
 111        for obj_name, obj in attrs.items():
 112            if _has_contribute_to_class(obj):
 113                contributable_attrs[obj_name] = obj
 114            else:
 115                new_attrs[obj_name] = obj
 116        new_class = super_new(cls, name, bases, new_attrs, **kwargs)
 117
 118        abstract = getattr(attr_meta, "abstract", False)
 119        meta = attr_meta or getattr(new_class, "Meta", None)
 120        base_meta = getattr(new_class, "_meta", None)
 121
 122        package_label = None
 123
 124        # Look for an application configuration to attach the model to.
 125        package_config = packages.get_containing_package_config(module)
 126
 127        if getattr(meta, "package_label", None) is None:
 128            if package_config is None:
 129                if not abstract:
 130                    raise RuntimeError(
 131                        f"Model class {module}.{name} doesn't declare an explicit "
 132                        "package_label and isn't in an application in "
 133                        "INSTALLED_PACKAGES."
 134                    )
 135
 136            else:
 137                package_label = package_config.label
 138
 139        new_class.add_to_class("_meta", Options(meta, package_label))
 140        if not abstract:
 141            new_class.add_to_class(
 142                "DoesNotExist",
 143                subclass_exception(
 144                    "DoesNotExist",
 145                    tuple(
 146                        x.DoesNotExist
 147                        for x in parents
 148                        if hasattr(x, "_meta") and not x._meta.abstract
 149                    )
 150                    or (ObjectDoesNotExist,),
 151                    module,
 152                    attached_to=new_class,
 153                ),
 154            )
 155            new_class.add_to_class(
 156                "MultipleObjectsReturned",
 157                subclass_exception(
 158                    "MultipleObjectsReturned",
 159                    tuple(
 160                        x.MultipleObjectsReturned
 161                        for x in parents
 162                        if hasattr(x, "_meta") and not x._meta.abstract
 163                    )
 164                    or (MultipleObjectsReturned,),
 165                    module,
 166                    attached_to=new_class,
 167                ),
 168            )
 169            if base_meta and not base_meta.abstract:
 170                # Non-abstract child classes inherit some attributes from their
 171                # non-abstract parent (unless an ABC comes before it in the
 172                # method resolution order).
 173                if not hasattr(meta, "ordering"):
 174                    new_class._meta.ordering = base_meta.ordering
 175                if not hasattr(meta, "get_latest_by"):
 176                    new_class._meta.get_latest_by = base_meta.get_latest_by
 177
 178        # Add remaining attributes (those with a contribute_to_class() method)
 179        # to the class.
 180        for obj_name, obj in contributable_attrs.items():
 181            new_class.add_to_class(obj_name, obj)
 182
 183        # All the fields of any type declared on this model
 184        new_fields = chain(
 185            new_class._meta.local_fields,
 186            new_class._meta.local_many_to_many,
 187            new_class._meta.private_fields,
 188        )
 189        field_names = {f.name for f in new_fields}
 190
 191        new_class._meta.concrete_model = new_class
 192
 193        # Collect the parent links for multi-table inheritance.
 194        parent_links = {}
 195        for base in reversed([new_class] + parents):
 196            # Conceptually equivalent to `if base is Model`.
 197            if not hasattr(base, "_meta"):
 198                continue
 199            # Skip concrete parent classes.
 200            if base != new_class and not base._meta.abstract:
 201                continue
 202            # Locate OneToOneField instances.
 203            for field in base._meta.local_fields:
 204                if isinstance(field, OneToOneField) and field.remote_field.parent_link:
 205                    related = resolve_relation(new_class, field.remote_field.model)
 206                    parent_links[make_model_tuple(related)] = field
 207
 208        # Track fields inherited from base models.
 209        inherited_attributes = set()
 210        # Do the appropriate setup for any model parents.
 211        for base in new_class.mro():
 212            if base not in parents or not hasattr(base, "_meta"):
 213                # Things without _meta aren't functional models, so they're
 214                # uninteresting parents.
 215                inherited_attributes.update(base.__dict__)
 216                continue
 217
 218            parent_fields = base._meta.local_fields + base._meta.local_many_to_many
 219            if not base._meta.abstract:
 220                # Check for clashes between locally declared fields and those
 221                # on the base classes.
 222                for field in parent_fields:
 223                    if field.name in field_names:
 224                        raise FieldError(
 225                            "Local field {!r} in class {!r} clashes with field of "
 226                            "the same name from base class {!r}.".format(
 227                                field.name,
 228                                name,
 229                                base.__name__,
 230                            )
 231                        )
 232                    else:
 233                        inherited_attributes.add(field.name)
 234
 235                # Concrete classes...
 236                base = base._meta.concrete_model
 237                base_key = make_model_tuple(base)
 238                if base_key in parent_links:
 239                    field = parent_links[base_key]
 240                else:
 241                    attr_name = "%s_ptr" % base._meta.model_name
 242                    field = OneToOneField(
 243                        base,
 244                        on_delete=CASCADE,
 245                        name=attr_name,
 246                        auto_created=True,
 247                        parent_link=True,
 248                    )
 249
 250                    if attr_name in field_names:
 251                        raise FieldError(
 252                            f"Auto-generated field '{attr_name}' in class {name!r} for "
 253                            f"parent_link to base class {base.__name__!r} clashes with "
 254                            "declared field of the same name."
 255                        )
 256
 257                    # Only add the ptr field if it's not already present;
 258                    # e.g. migrations will already have it specified
 259                    if not hasattr(new_class, attr_name):
 260                        new_class.add_to_class(attr_name, field)
 261                new_class._meta.parents[base] = field
 262            else:
 263                base_parents = base._meta.parents.copy()
 264
 265                # Add fields from abstract base class if it wasn't overridden.
 266                for field in parent_fields:
 267                    if (
 268                        field.name not in field_names
 269                        and field.name not in new_class.__dict__
 270                        and field.name not in inherited_attributes
 271                    ):
 272                        new_field = copy.deepcopy(field)
 273                        new_class.add_to_class(field.name, new_field)
 274                        # Replace parent links defined on this base by the new
 275                        # field. It will be appropriately resolved if required.
 276                        if field.one_to_one:
 277                            for parent, parent_link in base_parents.items():
 278                                if field == parent_link:
 279                                    base_parents[parent] = new_field
 280
 281                # Pass any non-abstract parent classes onto child.
 282                new_class._meta.parents.update(base_parents)
 283
 284            # Inherit private fields (like GenericForeignKey) from the parent
 285            # class
 286            for field in base._meta.private_fields:
 287                if field.name in field_names:
 288                    if not base._meta.abstract:
 289                        raise FieldError(
 290                            "Local field {!r} in class {!r} clashes with field of "
 291                            "the same name from base class {!r}.".format(
 292                                field.name,
 293                                name,
 294                                base.__name__,
 295                            )
 296                        )
 297                else:
 298                    field = copy.deepcopy(field)
 299                    if not base._meta.abstract:
 300                        field.mti_inherited = True
 301                    new_class.add_to_class(field.name, field)
 302
 303        # Copy indexes so that index names are unique when models extend an
 304        # abstract model.
 305        new_class._meta.indexes = [
 306            copy.deepcopy(idx) for idx in new_class._meta.indexes
 307        ]
 308
 309        if abstract:
 310            # Abstract base models can't be instantiated and don't appear in
 311            # the list of models for an app. We do the final setup for them a
 312            # little differently from normal models.
 313            attr_meta.abstract = False
 314            new_class.Meta = attr_meta
 315            return new_class
 316
 317        new_class._prepare()
 318        new_class._meta.packages.register_model(
 319            new_class._meta.package_label, new_class
 320        )
 321        return new_class
 322
 323    def add_to_class(cls, name, value):
 324        if _has_contribute_to_class(value):
 325            value.contribute_to_class(cls, name)
 326        else:
 327            setattr(cls, name, value)
 328
 329    def _prepare(cls):
 330        """Create some methods once self._meta has been populated."""
 331        opts = cls._meta
 332        opts._prepare(cls)
 333
 334        if opts.order_with_respect_to:
 335            cls.get_next_in_order = partialmethod(
 336                cls._get_next_or_previous_in_order, is_next=True
 337            )
 338            cls.get_previous_in_order = partialmethod(
 339                cls._get_next_or_previous_in_order, is_next=False
 340            )
 341
 342            # Defer creating accessors on the foreign class until it has been
 343            # created and registered. If remote_field is None, we're ordering
 344            # with respect to a GenericForeignKey and don't know what the
 345            # foreign class is - we'll add those accessors later in
 346            # contribute_to_class().
 347            if opts.order_with_respect_to.remote_field:
 348                wrt = opts.order_with_respect_to
 349                remote = wrt.remote_field.model
 350                lazy_related_operation(make_foreign_order_accessors, cls, remote)
 351
 352        # Give the class a docstring -- its definition.
 353        if cls.__doc__ is None:
 354            cls.__doc__ = "{}({})".format(
 355                cls.__name__,
 356                ", ".join(f.name for f in opts.fields),
 357            )
 358
 359        if not opts.managers:
 360            if any(f.name == "objects" for f in opts.fields):
 361                raise ValueError(
 362                    "Model %s must specify a custom Manager, because it has a "
 363                    "field named 'objects'." % cls.__name__
 364                )
 365            manager = Manager()
 366            manager.auto_created = True
 367            cls.add_to_class("objects", manager)
 368
 369        # Set the name of _meta.indexes. This can't be done in
 370        # Options.contribute_to_class() because fields haven't been added to
 371        # the model at that point.
 372        for index in cls._meta.indexes:
 373            if not index.name:
 374                index.set_name_with_model(cls)
 375
 376        class_prepared.send(sender=cls)
 377
 378    @property
 379    def _base_manager(cls):
 380        return cls._meta.base_manager
 381
 382    @property
 383    def _default_manager(cls):
 384        return cls._meta.default_manager
 385
 386
 387class ModelStateFieldsCacheDescriptor:
 388    def __get__(self, instance, cls=None):
 389        if instance is None:
 390            return self
 391        res = instance.fields_cache = {}
 392        return res
 393
 394
 395class ModelState:
 396    """Store model instance state."""
 397
 398    db = None
 399    # If true, uniqueness validation checks will consider this a new, unsaved
 400    # object. Necessary for correct validation of new instances of objects with
 401    # explicit (non-auto) PKs. This impacts validation only; it has no effect
 402    # on the actual save.
 403    adding = True
 404    fields_cache = ModelStateFieldsCacheDescriptor()
 405
 406
 407class Model(AltersData, metaclass=ModelBase):
 408    def __init__(self, *args, **kwargs):
 409        # Alias some things as locals to avoid repeat global lookups
 410        cls = self.__class__
 411        opts = self._meta
 412        _setattr = setattr
 413        _DEFERRED = DEFERRED
 414        if opts.abstract:
 415            raise TypeError("Abstract models cannot be instantiated.")
 416
 417        pre_init.send(sender=cls, args=args, kwargs=kwargs)
 418
 419        # Set up the storage for instance state
 420        self._state = ModelState()
 421
 422        # There is a rather weird disparity here; if kwargs, it's set, then args
 423        # overrides it. It should be one or the other; don't duplicate the work
 424        # The reason for the kwargs check is that standard iterator passes in by
 425        # args, and instantiation for iteration is 33% faster.
 426        if len(args) > len(opts.concrete_fields):
 427            # Daft, but matches old exception sans the err msg.
 428            raise IndexError("Number of args exceeds number of fields")
 429
 430        if not kwargs:
 431            fields_iter = iter(opts.concrete_fields)
 432            # The ordering of the zip calls matter - zip throws StopIteration
 433            # when an iter throws it. So if the first iter throws it, the second
 434            # is *not* consumed. We rely on this, so don't change the order
 435            # without changing the logic.
 436            for val, field in zip(args, fields_iter):
 437                if val is _DEFERRED:
 438                    continue
 439                _setattr(self, field.attname, val)
 440        else:
 441            # Slower, kwargs-ready version.
 442            fields_iter = iter(opts.fields)
 443            for val, field in zip(args, fields_iter):
 444                if val is _DEFERRED:
 445                    continue
 446                _setattr(self, field.attname, val)
 447                if kwargs.pop(field.name, NOT_PROVIDED) is not NOT_PROVIDED:
 448                    raise TypeError(
 449                        f"{cls.__qualname__}() got both positional and "
 450                        f"keyword arguments for field '{field.name}'."
 451                    )
 452
 453        # Now we're left with the unprocessed fields that *must* come from
 454        # keywords, or default.
 455
 456        for field in fields_iter:
 457            is_related_object = False
 458            # Virtual field
 459            if field.attname not in kwargs and field.column is None:
 460                continue
 461            if kwargs:
 462                if isinstance(field.remote_field, ForeignObjectRel):
 463                    try:
 464                        # Assume object instance was passed in.
 465                        rel_obj = kwargs.pop(field.name)
 466                        is_related_object = True
 467                    except KeyError:
 468                        try:
 469                            # Object instance wasn't passed in -- must be an ID.
 470                            val = kwargs.pop(field.attname)
 471                        except KeyError:
 472                            val = field.get_default()
 473                else:
 474                    try:
 475                        val = kwargs.pop(field.attname)
 476                    except KeyError:
 477                        # This is done with an exception rather than the
 478                        # default argument on pop because we don't want
 479                        # get_default() to be evaluated, and then not used.
 480                        # Refs #12057.
 481                        val = field.get_default()
 482            else:
 483                val = field.get_default()
 484
 485            if is_related_object:
 486                # If we are passed a related instance, set it using the
 487                # field.name instead of field.attname (e.g. "user" instead of
 488                # "user_id") so that the object gets properly cached (and type
 489                # checked) by the RelatedObjectDescriptor.
 490                if rel_obj is not _DEFERRED:
 491                    _setattr(self, field.name, rel_obj)
 492            else:
 493                if val is not _DEFERRED:
 494                    _setattr(self, field.attname, val)
 495
 496        if kwargs:
 497            property_names = opts._property_names
 498            unexpected = ()
 499            for prop, value in kwargs.items():
 500                # Any remaining kwargs must correspond to properties or virtual
 501                # fields.
 502                if prop in property_names:
 503                    if value is not _DEFERRED:
 504                        _setattr(self, prop, value)
 505                else:
 506                    try:
 507                        opts.get_field(prop)
 508                    except FieldDoesNotExist:
 509                        unexpected += (prop,)
 510                    else:
 511                        if value is not _DEFERRED:
 512                            _setattr(self, prop, value)
 513            if unexpected:
 514                unexpected_names = ", ".join(repr(n) for n in unexpected)
 515                raise TypeError(
 516                    f"{cls.__name__}() got unexpected keyword arguments: "
 517                    f"{unexpected_names}"
 518                )
 519        super().__init__()
 520        post_init.send(sender=cls, instance=self)
 521
 522    @classmethod
 523    def from_db(cls, db, field_names, values):
 524        if len(values) != len(cls._meta.concrete_fields):
 525            values_iter = iter(values)
 526            values = [
 527                next(values_iter) if f.attname in field_names else DEFERRED
 528                for f in cls._meta.concrete_fields
 529            ]
 530        new = cls(*values)
 531        new._state.adding = False
 532        new._state.db = db
 533        return new
 534
 535    def __repr__(self):
 536        return f"<{self.__class__.__name__}: {self}>"
 537
 538    def __str__(self):
 539        return f"{self.__class__.__name__} object ({self.pk})"
 540
 541    def __eq__(self, other):
 542        if not isinstance(other, Model):
 543            return NotImplemented
 544        if self._meta.concrete_model != other._meta.concrete_model:
 545            return False
 546        my_pk = self.pk
 547        if my_pk is None:
 548            return self is other
 549        return my_pk == other.pk
 550
 551    def __hash__(self):
 552        if self.pk is None:
 553            raise TypeError("Model instances without primary key value are unhashable")
 554        return hash(self.pk)
 555
 556    def __reduce__(self):
 557        data = self.__getstate__()
 558        data[PLAIN_VERSION_PICKLE_KEY] = plain.runtime.__version__
 559        class_id = self._meta.package_label, self._meta.object_name
 560        return model_unpickle, (class_id,), data
 561
 562    def __getstate__(self):
 563        """Hook to allow choosing the attributes to pickle."""
 564        state = self.__dict__.copy()
 565        state["_state"] = copy.copy(state["_state"])
 566        state["_state"].fields_cache = state["_state"].fields_cache.copy()
 567        # memoryview cannot be pickled, so cast it to bytes and store
 568        # separately.
 569        _memoryview_attrs = []
 570        for attr, value in state.items():
 571            if isinstance(value, memoryview):
 572                _memoryview_attrs.append((attr, bytes(value)))
 573        if _memoryview_attrs:
 574            state["_memoryview_attrs"] = _memoryview_attrs
 575            for attr, value in _memoryview_attrs:
 576                state.pop(attr)
 577        return state
 578
 579    def __setstate__(self, state):
 580        pickled_version = state.get(PLAIN_VERSION_PICKLE_KEY)
 581        if pickled_version:
 582            if pickled_version != plain.runtime.__version__:
 583                warnings.warn(
 584                    f"Pickled model instance's Plain version {pickled_version} does not "
 585                    f"match the current version {plain.runtime.__version__}.",
 586                    RuntimeWarning,
 587                    stacklevel=2,
 588                )
 589        else:
 590            warnings.warn(
 591                "Pickled model instance's Plain version is not specified.",
 592                RuntimeWarning,
 593                stacklevel=2,
 594            )
 595        if "_memoryview_attrs" in state:
 596            for attr, value in state.pop("_memoryview_attrs"):
 597                state[attr] = memoryview(value)
 598        self.__dict__.update(state)
 599
 600    def _get_pk_val(self, meta=None):
 601        meta = meta or self._meta
 602        return getattr(self, meta.pk.attname)
 603
 604    def _set_pk_val(self, value):
 605        for parent_link in self._meta.parents.values():
 606            if parent_link and parent_link != self._meta.pk:
 607                setattr(self, parent_link.target_field.attname, value)
 608        return setattr(self, self._meta.pk.attname, value)
 609
 610    pk = property(_get_pk_val, _set_pk_val)
 611
 612    def get_deferred_fields(self):
 613        """
 614        Return a set containing names of deferred fields for this instance.
 615        """
 616        return {
 617            f.attname
 618            for f in self._meta.concrete_fields
 619            if f.attname not in self.__dict__
 620        }
 621
 622    def refresh_from_db(self, using=None, fields=None):
 623        """
 624        Reload field values from the database.
 625
 626        By default, the reloading happens from the database this instance was
 627        loaded from, or by the read router if this instance wasn't loaded from
 628        any database. The using parameter will override the default.
 629
 630        Fields can be used to specify which fields to reload. The fields
 631        should be an iterable of field attnames. If fields is None, then
 632        all non-deferred fields are reloaded.
 633
 634        When accessing deferred fields of an instance, the deferred loading
 635        of the field will call this method.
 636        """
 637        if fields is None:
 638            self._prefetched_objects_cache = {}
 639        else:
 640            prefetched_objects_cache = getattr(self, "_prefetched_objects_cache", ())
 641            for field in fields:
 642                if field in prefetched_objects_cache:
 643                    del prefetched_objects_cache[field]
 644                    fields.remove(field)
 645            if not fields:
 646                return
 647            if any(LOOKUP_SEP in f for f in fields):
 648                raise ValueError(
 649                    'Found "%s" in fields argument. Relations and transforms '
 650                    "are not allowed in fields." % LOOKUP_SEP
 651                )
 652
 653        hints = {"instance": self}
 654        db_instance_qs = self.__class__._base_manager.db_manager(
 655            using, hints=hints
 656        ).filter(pk=self.pk)
 657
 658        # Use provided fields, if not set then reload all non-deferred fields.
 659        deferred_fields = self.get_deferred_fields()
 660        if fields is not None:
 661            fields = list(fields)
 662            db_instance_qs = db_instance_qs.only(*fields)
 663        elif deferred_fields:
 664            fields = [
 665                f.attname
 666                for f in self._meta.concrete_fields
 667                if f.attname not in deferred_fields
 668            ]
 669            db_instance_qs = db_instance_qs.only(*fields)
 670
 671        db_instance = db_instance_qs.get()
 672        non_loaded_fields = db_instance.get_deferred_fields()
 673        for field in self._meta.concrete_fields:
 674            if field.attname in non_loaded_fields:
 675                # This field wasn't refreshed - skip ahead.
 676                continue
 677            setattr(self, field.attname, getattr(db_instance, field.attname))
 678            # Clear cached foreign keys.
 679            if field.is_relation and field.is_cached(self):
 680                field.delete_cached_value(self)
 681
 682        # Clear cached relations.
 683        for field in self._meta.related_objects:
 684            if field.is_cached(self):
 685                field.delete_cached_value(self)
 686
 687        # Clear cached private relations.
 688        for field in self._meta.private_fields:
 689            if field.is_relation and field.is_cached(self):
 690                field.delete_cached_value(self)
 691
 692        self._state.db = db_instance._state.db
 693
 694    def serializable_value(self, field_name):
 695        """
 696        Return the value of the field name for this instance. If the field is
 697        a foreign key, return the id value instead of the object. If there's
 698        no Field object with this name on the model, return the model
 699        attribute's value.
 700
 701        Used to serialize a field's value (in the serializer, or form output,
 702        for example). Normally, you would just access the attribute directly
 703        and not use this method.
 704        """
 705        try:
 706            field = self._meta.get_field(field_name)
 707        except FieldDoesNotExist:
 708            return getattr(self, field_name)
 709        return getattr(self, field.attname)
 710
 711    def save(
 712        self,
 713        *,
 714        clean_and_validate=True,
 715        force_insert=False,
 716        force_update=False,
 717        using=None,
 718        update_fields=None,
 719    ):
 720        """
 721        Save the current instance. Override this in a subclass if you want to
 722        control the saving process.
 723
 724        The 'force_insert' and 'force_update' parameters can be used to insist
 725        that the "save" must be an SQL insert or update (or equivalent for
 726        non-SQL backends), respectively. Normally, they should not be set.
 727        """
 728        self._prepare_related_fields_for_save(operation_name="save")
 729
 730        using = using or router.db_for_write(self.__class__, instance=self)
 731        if force_insert and (force_update or update_fields):
 732            raise ValueError("Cannot force both insert and updating in model saving.")
 733
 734        deferred_fields = self.get_deferred_fields()
 735        if update_fields is not None:
 736            # If update_fields is empty, skip the save. We do also check for
 737            # no-op saves later on for inheritance cases. This bailout is
 738            # still needed for skipping signal sending.
 739            if not update_fields:
 740                return
 741
 742            update_fields = frozenset(update_fields)
 743            field_names = self._meta._non_pk_concrete_field_names
 744            non_model_fields = update_fields.difference(field_names)
 745
 746            if non_model_fields:
 747                raise ValueError(
 748                    "The following fields do not exist in this model, are m2m "
 749                    "fields, or are non-concrete fields: %s"
 750                    % ", ".join(non_model_fields)
 751                )
 752
 753        # If saving to the same database, and this model is deferred, then
 754        # automatically do an "update_fields" save on the loaded fields.
 755        elif not force_insert and deferred_fields and using == self._state.db:
 756            field_names = set()
 757            for field in self._meta.concrete_fields:
 758                if not field.primary_key and not hasattr(field, "through"):
 759                    field_names.add(field.attname)
 760            loaded_fields = field_names.difference(deferred_fields)
 761            if loaded_fields:
 762                update_fields = frozenset(loaded_fields)
 763
 764        if clean_and_validate:
 765            self.full_clean(exclude=deferred_fields)
 766
 767        self.save_base(
 768            using=using,
 769            force_insert=force_insert,
 770            force_update=force_update,
 771            update_fields=update_fields,
 772        )
 773
 774    save.alters_data = True
 775
 776    def save_base(
 777        self,
 778        *,
 779        raw=False,
 780        force_insert=False,
 781        force_update=False,
 782        using=None,
 783        update_fields=None,
 784    ):
 785        """
 786        Handle the parts of saving which should be done only once per save,
 787        yet need to be done in raw saves, too. This includes some sanity
 788        checks and signal sending.
 789
 790        The 'raw' argument is telling save_base not to save any parent
 791        models and not to do any changes to the values before save. This
 792        is used by fixture loading.
 793        """
 794        using = using or router.db_for_write(self.__class__, instance=self)
 795        assert not (force_insert and (force_update or update_fields))
 796        assert update_fields is None or update_fields
 797        cls = origin = self.__class__
 798        meta = cls._meta
 799        if not meta.auto_created:
 800            pre_save.send(
 801                sender=origin,
 802                instance=self,
 803                raw=raw,
 804                using=using,
 805                update_fields=update_fields,
 806            )
 807        # A transaction isn't needed if one query is issued.
 808        if meta.parents:
 809            context_manager = transaction.atomic(using=using, savepoint=False)
 810        else:
 811            context_manager = transaction.mark_for_rollback_on_error(using=using)
 812        with context_manager:
 813            parent_inserted = False
 814            if not raw:
 815                parent_inserted = self._save_parents(cls, using, update_fields)
 816            updated = self._save_table(
 817                raw,
 818                cls,
 819                force_insert or parent_inserted,
 820                force_update,
 821                using,
 822                update_fields,
 823            )
 824        # Store the database on which the object was saved
 825        self._state.db = using
 826        # Once saved, this is no longer a to-be-added instance.
 827        self._state.adding = False
 828
 829        # Signal that the save is complete
 830        if not meta.auto_created:
 831            post_save.send(
 832                sender=origin,
 833                instance=self,
 834                created=(not updated),
 835                update_fields=update_fields,
 836                raw=raw,
 837                using=using,
 838            )
 839
 840    save_base.alters_data = True
 841
 842    def _save_parents(self, cls, using, update_fields):
 843        """Save all the parents of cls using values from self."""
 844        meta = cls._meta
 845        inserted = False
 846        for parent, field in meta.parents.items():
 847            # Make sure the link fields are synced between parent and self.
 848            if (
 849                field
 850                and getattr(self, parent._meta.pk.attname) is None
 851                and getattr(self, field.attname) is not None
 852            ):
 853                setattr(self, parent._meta.pk.attname, getattr(self, field.attname))
 854            parent_inserted = self._save_parents(
 855                cls=parent, using=using, update_fields=update_fields
 856            )
 857            updated = self._save_table(
 858                cls=parent,
 859                using=using,
 860                update_fields=update_fields,
 861                force_insert=parent_inserted,
 862            )
 863            if not updated:
 864                inserted = True
 865            # Set the parent's PK value to self.
 866            if field:
 867                setattr(self, field.attname, self._get_pk_val(parent._meta))
 868                # Since we didn't have an instance of the parent handy set
 869                # attname directly, bypassing the descriptor. Invalidate
 870                # the related object cache, in case it's been accidentally
 871                # populated. A fresh instance will be re-built from the
 872                # database if necessary.
 873                if field.is_cached(self):
 874                    field.delete_cached_value(self)
 875        return inserted
 876
 877    def _save_table(
 878        self,
 879        raw=False,
 880        cls=None,
 881        force_insert=False,
 882        force_update=False,
 883        using=None,
 884        update_fields=None,
 885    ):
 886        """
 887        Do the heavy-lifting involved in saving. Update or insert the data
 888        for a single table.
 889        """
 890        meta = cls._meta
 891        non_pks = [f for f in meta.local_concrete_fields if not f.primary_key]
 892
 893        if update_fields:
 894            non_pks = [
 895                f
 896                for f in non_pks
 897                if f.name in update_fields or f.attname in update_fields
 898            ]
 899
 900        pk_val = self._get_pk_val(meta)
 901        if pk_val is None:
 902            pk_val = meta.pk.get_pk_value_on_save(self)
 903            setattr(self, meta.pk.attname, pk_val)
 904        pk_set = pk_val is not None
 905        if not pk_set and (force_update or update_fields):
 906            raise ValueError("Cannot force an update in save() with no primary key.")
 907        updated = False
 908        # Skip an UPDATE when adding an instance and primary key has a default.
 909        if (
 910            not raw
 911            and not force_insert
 912            and self._state.adding
 913            and meta.pk.default
 914            and meta.pk.default is not NOT_PROVIDED
 915        ):
 916            force_insert = True
 917        # If possible, try an UPDATE. If that doesn't update anything, do an INSERT.
 918        if pk_set and not force_insert:
 919            base_qs = cls._base_manager.using(using)
 920            values = [
 921                (
 922                    f,
 923                    None,
 924                    (getattr(self, f.attname) if raw else f.pre_save(self, False)),
 925                )
 926                for f in non_pks
 927            ]
 928            forced_update = update_fields or force_update
 929            updated = self._do_update(
 930                base_qs, using, pk_val, values, update_fields, forced_update
 931            )
 932            if force_update and not updated:
 933                raise DatabaseError("Forced update did not affect any rows.")
 934            if update_fields and not updated:
 935                raise DatabaseError("Save with update_fields did not affect any rows.")
 936        if not updated:
 937            if meta.order_with_respect_to:
 938                # If this is a model with an order_with_respect_to
 939                # autopopulate the _order field
 940                field = meta.order_with_respect_to
 941                filter_args = field.get_filter_kwargs_for_object(self)
 942                self._order = (
 943                    cls._base_manager.using(using)
 944                    .filter(**filter_args)
 945                    .aggregate(
 946                        _order__max=Coalesce(
 947                            ExpressionWrapper(
 948                                Max("_order") + Value(1), output_field=IntegerField()
 949                            ),
 950                            Value(0),
 951                        ),
 952                    )["_order__max"]
 953                )
 954            fields = meta.local_concrete_fields
 955            if not pk_set:
 956                fields = [f for f in fields if f is not meta.auto_field]
 957
 958            returning_fields = meta.db_returning_fields
 959            results = self._do_insert(
 960                cls._base_manager, using, fields, returning_fields, raw
 961            )
 962            if results:
 963                for value, field in zip(results[0], returning_fields):
 964                    setattr(self, field.attname, value)
 965        return updated
 966
 967    def _do_update(self, base_qs, using, pk_val, values, update_fields, forced_update):
 968        """
 969        Try to update the model. Return True if the model was updated (if an
 970        update query was done and a matching row was found in the DB).
 971        """
 972        filtered = base_qs.filter(pk=pk_val)
 973        if not values:
 974            # We can end up here when saving a model in inheritance chain where
 975            # update_fields doesn't target any field in current model. In that
 976            # case we just say the update succeeded. Another case ending up here
 977            # is a model with just PK - in that case check that the PK still
 978            # exists.
 979            return update_fields is not None or filtered.exists()
 980        if self._meta.select_on_save and not forced_update:
 981            return (
 982                filtered.exists()
 983                and
 984                # It may happen that the object is deleted from the DB right after
 985                # this check, causing the subsequent UPDATE to return zero matching
 986                # rows. The same result can occur in some rare cases when the
 987                # database returns zero despite the UPDATE being executed
 988                # successfully (a row is matched and updated). In order to
 989                # distinguish these two cases, the object's existence in the
 990                # database is again checked for if the UPDATE query returns 0.
 991                (filtered._update(values) > 0 or filtered.exists())
 992            )
 993        return filtered._update(values) > 0
 994
 995    def _do_insert(self, manager, using, fields, returning_fields, raw):
 996        """
 997        Do an INSERT. If returning_fields is defined then this method should
 998        return the newly created data for the model.
 999        """
1000        return manager._insert(
1001            [self],
1002            fields=fields,
1003            returning_fields=returning_fields,
1004            using=using,
1005            raw=raw,
1006        )
1007
1008    def _prepare_related_fields_for_save(self, operation_name, fields=None):
1009        # Ensure that a model instance without a PK hasn't been assigned to
1010        # a ForeignKey, GenericForeignKey or OneToOneField on this model. If
1011        # the field is nullable, allowing the save would result in silent data
1012        # loss.
1013        for field in self._meta.concrete_fields:
1014            if fields and field not in fields:
1015                continue
1016            # If the related field isn't cached, then an instance hasn't been
1017            # assigned and there's no need to worry about this check.
1018            if field.is_relation and field.is_cached(self):
1019                obj = getattr(self, field.name, None)
1020                if not obj:
1021                    continue
1022                # A pk may have been assigned manually to a model instance not
1023                # saved to the database (or auto-generated in a case like
1024                # UUIDField), but we allow the save to proceed and rely on the
1025                # database to raise an IntegrityError if applicable. If
1026                # constraints aren't supported by the database, there's the
1027                # unavoidable risk of data corruption.
1028                if obj.pk is None:
1029                    # Remove the object from a related instance cache.
1030                    if not field.remote_field.multiple:
1031                        field.remote_field.delete_cached_value(obj)
1032                    raise ValueError(
1033                        "{}() prohibited to prevent data loss due to unsaved "
1034                        "related object '{}'.".format(operation_name, field.name)
1035                    )
1036                elif getattr(self, field.attname) in field.empty_values:
1037                    # Set related object if it has been saved after an
1038                    # assignment.
1039                    setattr(self, field.name, obj)
1040                # If the relationship's pk/to_field was changed, clear the
1041                # cached relationship.
1042                if getattr(obj, field.target_field.attname) != getattr(
1043                    self, field.attname
1044                ):
1045                    field.delete_cached_value(self)
1046        # GenericForeignKeys are private.
1047        for field in self._meta.private_fields:
1048            if fields and field not in fields:
1049                continue
1050            if (
1051                field.is_relation
1052                and field.is_cached(self)
1053                and hasattr(field, "fk_field")
1054            ):
1055                obj = field.get_cached_value(self, default=None)
1056                if obj and obj.pk is None:
1057                    raise ValueError(
1058                        f"{operation_name}() prohibited to prevent data loss due to "
1059                        f"unsaved related object '{field.name}'."
1060                    )
1061
1062    def delete(self, using=None, keep_parents=False):
1063        if self.pk is None:
1064            raise ValueError(
1065                "{} object can't be deleted because its {} attribute is set "
1066                "to None.".format(self._meta.object_name, self._meta.pk.attname)
1067            )
1068        using = using or router.db_for_write(self.__class__, instance=self)
1069        collector = Collector(using=using, origin=self)
1070        collector.collect([self], keep_parents=keep_parents)
1071        return collector.delete()
1072
1073    delete.alters_data = True
1074
1075    def _get_FIELD_display(self, field):
1076        value = getattr(self, field.attname)
1077        choices_dict = dict(make_hashable(field.flatchoices))
1078        # force_str() to coerce lazy strings.
1079        return force_str(
1080            choices_dict.get(make_hashable(value), value), strings_only=True
1081        )
1082
1083    def _get_next_or_previous_by_FIELD(self, field, is_next, **kwargs):
1084        if not self.pk:
1085            raise ValueError("get_next/get_previous cannot be used on unsaved objects.")
1086        op = "gt" if is_next else "lt"
1087        order = "" if is_next else "-"
1088        param = getattr(self, field.attname)
1089        q = Q.create([(field.name, param), (f"pk__{op}", self.pk)], connector=Q.AND)
1090        q = Q.create([q, (f"{field.name}__{op}", param)], connector=Q.OR)
1091        qs = (
1092            self.__class__._default_manager.using(self._state.db)
1093            .filter(**kwargs)
1094            .filter(q)
1095            .order_by(f"{order}{field.name}", "%spk" % order)
1096        )
1097        try:
1098            return qs[0]
1099        except IndexError:
1100            raise self.DoesNotExist(
1101                "%s matching query does not exist." % self.__class__._meta.object_name
1102            )
1103
1104    def _get_next_or_previous_in_order(self, is_next):
1105        cachename = "__%s_order_cache" % is_next
1106        if not hasattr(self, cachename):
1107            op = "gt" if is_next else "lt"
1108            order = "_order" if is_next else "-_order"
1109            order_field = self._meta.order_with_respect_to
1110            filter_args = order_field.get_filter_kwargs_for_object(self)
1111            obj = (
1112                self.__class__._default_manager.filter(**filter_args)
1113                .filter(
1114                    **{
1115                        "_order__%s" % op: self.__class__._default_manager.values(
1116                            "_order"
1117                        ).filter(**{self._meta.pk.name: self.pk})
1118                    }
1119                )
1120                .order_by(order)[:1]
1121                .get()
1122            )
1123            setattr(self, cachename, obj)
1124        return getattr(self, cachename)
1125
1126    def _get_field_value_map(self, meta, exclude=None):
1127        if exclude is None:
1128            exclude = set()
1129        meta = meta or self._meta
1130        return {
1131            field.name: Value(getattr(self, field.attname), field)
1132            for field in meta.local_concrete_fields
1133            if field.name not in exclude
1134        }
1135
1136    def prepare_database_save(self, field):
1137        if self.pk is None:
1138            raise ValueError(
1139                "Unsaved model instance %r cannot be used in an ORM query." % self
1140            )
1141        return getattr(self, field.remote_field.get_related_field().attname)
1142
1143    def clean(self):
1144        """
1145        Hook for doing any extra model-wide validation after clean() has been
1146        called on every field by self.clean_fields. Any ValidationError raised
1147        by this method will not be associated with a particular field; it will
1148        have a special-case association with the field defined by NON_FIELD_ERRORS.
1149        """
1150        pass
1151
1152    def validate_unique(self, exclude=None):
1153        """
1154        Check unique constraints on the model and raise ValidationError if any
1155        failed.
1156        """
1157        unique_checks = self._get_unique_checks(exclude=exclude)
1158
1159        if errors := self._perform_unique_checks(unique_checks):
1160            raise ValidationError(errors)
1161
1162    def _get_unique_checks(self, exclude=None):
1163        """
1164        Return a list of checks to perform. Since validate_unique() could be
1165        called from a ModelForm, some fields may have been excluded; we can't
1166        perform a unique check on a model that is missing fields involved
1167        in that check. Fields that did not validate should also be excluded,
1168        but they need to be passed in via the exclude argument.
1169        """
1170        if exclude is None:
1171            exclude = set()
1172        unique_checks = []
1173
1174        # Gather a list of checks for fields declared as unique and add them to
1175        # the list of checks.
1176
1177        fields_with_class = [(self.__class__, self._meta.local_fields)]
1178        for parent_class in self._meta.get_parent_list():
1179            fields_with_class.append((parent_class, parent_class._meta.local_fields))
1180
1181        for model_class, fields in fields_with_class:
1182            for f in fields:
1183                name = f.name
1184                if name in exclude:
1185                    continue
1186                if f.unique:
1187                    unique_checks.append((model_class, (name,)))
1188
1189        return unique_checks
1190
1191    def _perform_unique_checks(self, unique_checks):
1192        errors = {}
1193
1194        for model_class, unique_check in unique_checks:
1195            # Try to look up an existing object with the same values as this
1196            # object's values for all the unique field.
1197
1198            lookup_kwargs = {}
1199            for field_name in unique_check:
1200                f = self._meta.get_field(field_name)
1201                lookup_value = getattr(self, f.attname)
1202                # TODO: Handle multiple backends with different feature flags.
1203                if lookup_value is None or (
1204                    lookup_value == ""
1205                    and connection.features.interprets_empty_strings_as_nulls
1206                ):
1207                    # no value, skip the lookup
1208                    continue
1209                if f.primary_key and not self._state.adding:
1210                    # no need to check for unique primary key when editing
1211                    continue
1212                lookup_kwargs[str(field_name)] = lookup_value
1213
1214            # some fields were skipped, no reason to do the check
1215            if len(unique_check) != len(lookup_kwargs):
1216                continue
1217
1218            qs = model_class._default_manager.filter(**lookup_kwargs)
1219
1220            # Exclude the current object from the query if we are editing an
1221            # instance (as opposed to creating a new one)
1222            # Note that we need to use the pk as defined by model_class, not
1223            # self.pk. These can be different fields because model inheritance
1224            # allows single model to have effectively multiple primary keys.
1225            # Refs #17615.
1226            model_class_pk = self._get_pk_val(model_class._meta)
1227            if not self._state.adding and model_class_pk is not None:
1228                qs = qs.exclude(pk=model_class_pk)
1229            if qs.exists():
1230                if len(unique_check) == 1:
1231                    key = unique_check[0]
1232                else:
1233                    key = NON_FIELD_ERRORS
1234                errors.setdefault(key, []).append(
1235                    self.unique_error_message(model_class, unique_check)
1236                )
1237
1238        return errors
1239
1240    def unique_error_message(self, model_class, unique_check):
1241        opts = model_class._meta
1242
1243        params = {
1244            "model": self,
1245            "model_class": model_class,
1246            "model_name": opts.model_name,
1247            "unique_check": unique_check,
1248        }
1249
1250        if len(unique_check) == 1:
1251            field = opts.get_field(unique_check[0])
1252            params["field_label"] = field.name
1253            return ValidationError(
1254                message=field.error_messages["unique"],
1255                code="unique",
1256                params=params,
1257            )
1258        else:
1259            field_names = [opts.get_field(f).name for f in unique_check]
1260
1261            # Put an "and" before the last one
1262            field_names[-1] = f"and {field_names[-1]}"
1263
1264            if len(field_names) > 2:
1265                # Comma join if more than 2
1266                params["field_label"] = ", ".join(field_names)
1267            else:
1268                # Just a space if there are only 2
1269                params["field_label"] = " ".join(field_names)
1270
1271            # Use the first field as the message format...
1272            message = opts.get_field(unique_check[0]).error_messages["unique"]
1273
1274            return ValidationError(
1275                message=message,
1276                code="unique",
1277                params=params,
1278            )
1279
1280    def get_constraints(self):
1281        constraints = [(self.__class__, self._meta.constraints)]
1282        for parent_class in self._meta.get_parent_list():
1283            if parent_class._meta.constraints:
1284                constraints.append((parent_class, parent_class._meta.constraints))
1285        return constraints
1286
1287    def validate_constraints(self, exclude=None):
1288        constraints = self.get_constraints()
1289        using = router.db_for_write(self.__class__, instance=self)
1290
1291        errors = {}
1292        for model_class, model_constraints in constraints:
1293            for constraint in model_constraints:
1294                try:
1295                    constraint.validate(model_class, self, exclude=exclude, using=using)
1296                except ValidationError as e:
1297                    if (
1298                        getattr(e, "code", None) == "unique"
1299                        and len(constraint.fields) == 1
1300                    ):
1301                        errors.setdefault(constraint.fields[0], []).append(e)
1302                    else:
1303                        errors = e.update_error_dict(errors)
1304        if errors:
1305            raise ValidationError(errors)
1306
1307    def full_clean(
1308        self, *, exclude=None, validate_unique=True, validate_constraints=True
1309    ):
1310        """
1311        Call clean_fields(), clean(), validate_unique(), and
1312        validate_constraints() on the model. Raise a ValidationError for any
1313        errors that occur.
1314        """
1315        errors = {}
1316        if exclude is None:
1317            exclude = set()
1318        else:
1319            exclude = set(exclude)
1320
1321        try:
1322            self.clean_fields(exclude=exclude)
1323        except ValidationError as e:
1324            errors = e.update_error_dict(errors)
1325
1326        # Form.clean() is run even if other validation fails, so do the
1327        # same with Model.clean() for consistency.
1328        try:
1329            self.clean()
1330        except ValidationError as e:
1331            errors = e.update_error_dict(errors)
1332
1333        # Run unique checks, but only for fields that passed validation.
1334        if validate_unique:
1335            for name in errors:
1336                if name != NON_FIELD_ERRORS and name not in exclude:
1337                    exclude.add(name)
1338            try:
1339                self.validate_unique(exclude=exclude)
1340            except ValidationError as e:
1341                errors = e.update_error_dict(errors)
1342
1343        # Run constraints checks, but only for fields that passed validation.
1344        if validate_constraints:
1345            for name in errors:
1346                if name != NON_FIELD_ERRORS and name not in exclude:
1347                    exclude.add(name)
1348            try:
1349                self.validate_constraints(exclude=exclude)
1350            except ValidationError as e:
1351                errors = e.update_error_dict(errors)
1352
1353        if errors:
1354            raise ValidationError(errors)
1355
1356    def clean_fields(self, exclude=None):
1357        """
1358        Clean all fields and raise a ValidationError containing a dict
1359        of all validation errors if any occur.
1360        """
1361        if exclude is None:
1362            exclude = set()
1363
1364        errors = {}
1365        for f in self._meta.fields:
1366            if f.name in exclude:
1367                continue
1368            # Skip validation for empty fields with blank=True. The developer
1369            # is responsible for making sure they have a valid value.
1370            raw_value = getattr(self, f.attname)
1371            if f.blank and raw_value in f.empty_values:
1372                continue
1373            try:
1374                setattr(self, f.attname, f.clean(raw_value, self))
1375            except ValidationError as e:
1376                errors[f.name] = e.error_list
1377
1378        if errors:
1379            raise ValidationError(errors)
1380
1381    @classmethod
1382    def check(cls, **kwargs):
1383        errors = [
1384            *cls._check_swappable(),
1385            *cls._check_managers(**kwargs),
1386        ]
1387        if not cls._meta.swapped:
1388            databases = kwargs.get("databases") or []
1389            errors += [
1390                *cls._check_fields(**kwargs),
1391                *cls._check_m2m_through_same_relationship(),
1392                *cls._check_long_column_names(databases),
1393            ]
1394            clash_errors = (
1395                *cls._check_id_field(),
1396                *cls._check_field_name_clashes(),
1397                *cls._check_model_name_db_lookup_clashes(),
1398                *cls._check_property_name_related_field_accessor_clashes(),
1399                *cls._check_single_primary_key(),
1400            )
1401            errors.extend(clash_errors)
1402            # If there are field name clashes, hide consequent column name
1403            # clashes.
1404            if not clash_errors:
1405                errors.extend(cls._check_column_name_clashes())
1406            errors += [
1407                *cls._check_indexes(databases),
1408                *cls._check_ordering(),
1409                *cls._check_constraints(databases),
1410                *cls._check_db_table_comment(databases),
1411            ]
1412
1413        return errors
1414
1415    @classmethod
1416    def _check_db_table_comment(cls, databases):
1417        if not cls._meta.db_table_comment:
1418            return []
1419        errors = []
1420        for db in databases:
1421            if not router.allow_migrate_model(db, cls):
1422                continue
1423            connection = connections[db]
1424            if not (
1425                connection.features.supports_comments
1426                or "supports_comments" in cls._meta.required_db_features
1427            ):
1428                errors.append(
1429                    preflight.Warning(
1430                        f"{connection.display_name} does not support comments on "
1431                        f"tables (db_table_comment).",
1432                        obj=cls,
1433                        id="models.W046",
1434                    )
1435                )
1436        return errors
1437
1438    @classmethod
1439    def _check_swappable(cls):
1440        """Check if the swapped model exists."""
1441        errors = []
1442        if cls._meta.swapped:
1443            try:
1444                packages.get_model(cls._meta.swapped)
1445            except ValueError:
1446                errors.append(
1447                    preflight.Error(
1448                        "'%s' is not of the form 'package_label.package_name'."
1449                        % cls._meta.swappable,
1450                        id="models.E001",
1451                    )
1452                )
1453            except LookupError:
1454                package_label, model_name = cls._meta.swapped.split(".")
1455                errors.append(
1456                    preflight.Error(
1457                        "'{}' references '{}.{}', which has not been "
1458                        "installed, or is abstract.".format(
1459                            cls._meta.swappable, package_label, model_name
1460                        ),
1461                        id="models.E002",
1462                    )
1463                )
1464        return errors
1465
1466    @classmethod
1467    def _check_managers(cls, **kwargs):
1468        """Perform all manager checks."""
1469        errors = []
1470        for manager in cls._meta.managers:
1471            errors.extend(manager.check(**kwargs))
1472        return errors
1473
1474    @classmethod
1475    def _check_fields(cls, **kwargs):
1476        """Perform all field checks."""
1477        errors = []
1478        for field in cls._meta.local_fields:
1479            errors.extend(field.check(**kwargs))
1480        for field in cls._meta.local_many_to_many:
1481            errors.extend(field.check(from_model=cls, **kwargs))
1482        return errors
1483
1484    @classmethod
1485    def _check_m2m_through_same_relationship(cls):
1486        """Check if no relationship model is used by more than one m2m field."""
1487
1488        errors = []
1489        seen_intermediary_signatures = []
1490
1491        fields = cls._meta.local_many_to_many
1492
1493        # Skip when the target model wasn't found.
1494        fields = (f for f in fields if isinstance(f.remote_field.model, ModelBase))
1495
1496        # Skip when the relationship model wasn't found.
1497        fields = (f for f in fields if isinstance(f.remote_field.through, ModelBase))
1498
1499        for f in fields:
1500            signature = (
1501                f.remote_field.model,
1502                cls,
1503                f.remote_field.through,
1504                f.remote_field.through_fields,
1505            )
1506            if signature in seen_intermediary_signatures:
1507                errors.append(
1508                    preflight.Error(
1509                        "The model has two identical many-to-many relations "
1510                        "through the intermediate model '%s'."
1511                        % f.remote_field.through._meta.label,
1512                        obj=cls,
1513                        id="models.E003",
1514                    )
1515                )
1516            else:
1517                seen_intermediary_signatures.append(signature)
1518        return errors
1519
1520    @classmethod
1521    def _check_id_field(cls):
1522        """Check if `id` field is a primary key."""
1523        fields = [
1524            f for f in cls._meta.local_fields if f.name == "id" and f != cls._meta.pk
1525        ]
1526        # fields is empty or consists of the invalid "id" field
1527        if fields and not fields[0].primary_key and cls._meta.pk.name == "id":
1528            return [
1529                preflight.Error(
1530                    "'id' can only be used as a field name if the field also "
1531                    "sets 'primary_key=True'.",
1532                    obj=cls,
1533                    id="models.E004",
1534                )
1535            ]
1536        else:
1537            return []
1538
1539    @classmethod
1540    def _check_field_name_clashes(cls):
1541        """Forbid field shadowing in multi-table inheritance."""
1542        errors = []
1543        used_fields = {}  # name or attname -> field
1544
1545        # Check that multi-inheritance doesn't cause field name shadowing.
1546        for parent in cls._meta.get_parent_list():
1547            for f in parent._meta.local_fields:
1548                clash = used_fields.get(f.name) or used_fields.get(f.attname) or None
1549                if clash:
1550                    errors.append(
1551                        preflight.Error(
1552                            f"The field '{clash.name}' from parent model "
1553                            f"'{clash.model._meta}' clashes with the field '{f.name}' "
1554                            f"from parent model '{f.model._meta}'.",
1555                            obj=cls,
1556                            id="models.E005",
1557                        )
1558                    )
1559                used_fields[f.name] = f
1560                used_fields[f.attname] = f
1561
1562        # Check that fields defined in the model don't clash with fields from
1563        # parents, including auto-generated fields like multi-table inheritance
1564        # child accessors.
1565        for parent in cls._meta.get_parent_list():
1566            for f in parent._meta.get_fields():
1567                if f not in used_fields:
1568                    used_fields[f.name] = f
1569
1570        for f in cls._meta.local_fields:
1571            clash = used_fields.get(f.name) or used_fields.get(f.attname) or None
1572            # Note that we may detect clash between user-defined non-unique
1573            # field "id" and automatically added unique field "id", both
1574            # defined at the same model. This special case is considered in
1575            # _check_id_field and here we ignore it.
1576            id_conflict = (
1577                f.name == "id" and clash and clash.name == "id" and clash.model == cls
1578            )
1579            if clash and not id_conflict:
1580                errors.append(
1581                    preflight.Error(
1582                        f"The field '{f.name}' clashes with the field '{clash.name}' "
1583                        f"from model '{clash.model._meta}'.",
1584                        obj=f,
1585                        id="models.E006",
1586                    )
1587                )
1588            used_fields[f.name] = f
1589            used_fields[f.attname] = f
1590
1591        return errors
1592
1593    @classmethod
1594    def _check_column_name_clashes(cls):
1595        # Store a list of column names which have already been used by other fields.
1596        used_column_names = []
1597        errors = []
1598
1599        for f in cls._meta.local_fields:
1600            _, column_name = f.get_attname_column()
1601
1602            # Ensure the column name is not already in use.
1603            if column_name and column_name in used_column_names:
1604                errors.append(
1605                    preflight.Error(
1606                        "Field '{}' has column name '{}' that is used by "
1607                        "another field.".format(f.name, column_name),
1608                        hint="Specify a 'db_column' for the field.",
1609                        obj=cls,
1610                        id="models.E007",
1611                    )
1612                )
1613            else:
1614                used_column_names.append(column_name)
1615
1616        return errors
1617
1618    @classmethod
1619    def _check_model_name_db_lookup_clashes(cls):
1620        errors = []
1621        model_name = cls.__name__
1622        if model_name.startswith("_") or model_name.endswith("_"):
1623            errors.append(
1624                preflight.Error(
1625                    "The model name '%s' cannot start or end with an underscore "
1626                    "as it collides with the query lookup syntax." % model_name,
1627                    obj=cls,
1628                    id="models.E023",
1629                )
1630            )
1631        elif LOOKUP_SEP in model_name:
1632            errors.append(
1633                preflight.Error(
1634                    "The model name '%s' cannot contain double underscores as "
1635                    "it collides with the query lookup syntax." % model_name,
1636                    obj=cls,
1637                    id="models.E024",
1638                )
1639            )
1640        return errors
1641
1642    @classmethod
1643    def _check_property_name_related_field_accessor_clashes(cls):
1644        errors = []
1645        property_names = cls._meta._property_names
1646        related_field_accessors = (
1647            f.get_attname()
1648            for f in cls._meta._get_fields(reverse=False)
1649            if f.is_relation and f.related_model is not None
1650        )
1651        for accessor in related_field_accessors:
1652            if accessor in property_names:
1653                errors.append(
1654                    preflight.Error(
1655                        "The property '%s' clashes with a related field "
1656                        "accessor." % accessor,
1657                        obj=cls,
1658                        id="models.E025",
1659                    )
1660                )
1661        return errors
1662
1663    @classmethod
1664    def _check_single_primary_key(cls):
1665        errors = []
1666        if sum(1 for f in cls._meta.local_fields if f.primary_key) > 1:
1667            errors.append(
1668                preflight.Error(
1669                    "The model cannot have more than one field with "
1670                    "'primary_key=True'.",
1671                    obj=cls,
1672                    id="models.E026",
1673                )
1674            )
1675        return errors
1676
1677    @classmethod
1678    def _check_indexes(cls, databases):
1679        """Check fields, names, and conditions of indexes."""
1680        errors = []
1681        references = set()
1682        for index in cls._meta.indexes:
1683            # Index name can't start with an underscore or a number, restricted
1684            # for cross-database compatibility with Oracle.
1685            if index.name[0] == "_" or index.name[0].isdigit():
1686                errors.append(
1687                    preflight.Error(
1688                        "The index name '%s' cannot start with an underscore "
1689                        "or a number." % index.name,
1690                        obj=cls,
1691                        id="models.E033",
1692                    ),
1693                )
1694            if len(index.name) > index.max_name_length:
1695                errors.append(
1696                    preflight.Error(
1697                        "The index name '%s' cannot be longer than %d "
1698                        "characters." % (index.name, index.max_name_length),
1699                        obj=cls,
1700                        id="models.E034",
1701                    ),
1702                )
1703            if index.contains_expressions:
1704                for expression in index.expressions:
1705                    references.update(
1706                        ref[0] for ref in cls._get_expr_references(expression)
1707                    )
1708        for db in databases:
1709            if not router.allow_migrate_model(db, cls):
1710                continue
1711            connection = connections[db]
1712            if not (
1713                connection.features.supports_partial_indexes
1714                or "supports_partial_indexes" in cls._meta.required_db_features
1715            ) and any(index.condition is not None for index in cls._meta.indexes):
1716                errors.append(
1717                    preflight.Warning(
1718                        "%s does not support indexes with conditions."
1719                        % connection.display_name,
1720                        hint=(
1721                            "Conditions will be ignored. Silence this warning "
1722                            "if you don't care about it."
1723                        ),
1724                        obj=cls,
1725                        id="models.W037",
1726                    )
1727                )
1728            if not (
1729                connection.features.supports_covering_indexes
1730                or "supports_covering_indexes" in cls._meta.required_db_features
1731            ) and any(index.include for index in cls._meta.indexes):
1732                errors.append(
1733                    preflight.Warning(
1734                        "%s does not support indexes with non-key columns."
1735                        % connection.display_name,
1736                        hint=(
1737                            "Non-key columns will be ignored. Silence this "
1738                            "warning if you don't care about it."
1739                        ),
1740                        obj=cls,
1741                        id="models.W040",
1742                    )
1743                )
1744            if not (
1745                connection.features.supports_expression_indexes
1746                or "supports_expression_indexes" in cls._meta.required_db_features
1747            ) and any(index.contains_expressions for index in cls._meta.indexes):
1748                errors.append(
1749                    preflight.Warning(
1750                        "%s does not support indexes on expressions."
1751                        % connection.display_name,
1752                        hint=(
1753                            "An index won't be created. Silence this warning "
1754                            "if you don't care about it."
1755                        ),
1756                        obj=cls,
1757                        id="models.W043",
1758                    )
1759                )
1760        fields = [
1761            field for index in cls._meta.indexes for field, _ in index.fields_orders
1762        ]
1763        fields += [include for index in cls._meta.indexes for include in index.include]
1764        fields += references
1765        errors.extend(cls._check_local_fields(fields, "indexes"))
1766        return errors
1767
1768    @classmethod
1769    def _check_local_fields(cls, fields, option):
1770        from plain import models
1771
1772        # In order to avoid hitting the relation tree prematurely, we use our
1773        # own fields_map instead of using get_field()
1774        forward_fields_map = {}
1775        for field in cls._meta._get_fields(reverse=False):
1776            forward_fields_map[field.name] = field
1777            if hasattr(field, "attname"):
1778                forward_fields_map[field.attname] = field
1779
1780        errors = []
1781        for field_name in fields:
1782            try:
1783                field = forward_fields_map[field_name]
1784            except KeyError:
1785                errors.append(
1786                    preflight.Error(
1787                        f"'{option}' refers to the nonexistent field '{field_name}'.",
1788                        obj=cls,
1789                        id="models.E012",
1790                    )
1791                )
1792            else:
1793                if isinstance(field.remote_field, models.ManyToManyRel):
1794                    errors.append(
1795                        preflight.Error(
1796                            "'{}' refers to a ManyToManyField '{}', but "
1797                            "ManyToManyFields are not permitted in '{}'.".format(
1798                                option,
1799                                field_name,
1800                                option,
1801                            ),
1802                            obj=cls,
1803                            id="models.E013",
1804                        )
1805                    )
1806                elif field not in cls._meta.local_fields:
1807                    errors.append(
1808                        preflight.Error(
1809                            "'{}' refers to field '{}' which is not local to model "
1810                            "'{}'.".format(option, field_name, cls._meta.object_name),
1811                            hint="This issue may be caused by multi-table inheritance.",
1812                            obj=cls,
1813                            id="models.E016",
1814                        )
1815                    )
1816        return errors
1817
1818    @classmethod
1819    def _check_ordering(cls):
1820        """
1821        Check "ordering" option -- is it a list of strings and do all fields
1822        exist?
1823        """
1824        if cls._meta._ordering_clash:
1825            return [
1826                preflight.Error(
1827                    "'ordering' and 'order_with_respect_to' cannot be used together.",
1828                    obj=cls,
1829                    id="models.E021",
1830                ),
1831            ]
1832
1833        if cls._meta.order_with_respect_to or not cls._meta.ordering:
1834            return []
1835
1836        if not isinstance(cls._meta.ordering, list | tuple):
1837            return [
1838                preflight.Error(
1839                    "'ordering' must be a tuple or list (even if you want to order by "
1840                    "only one field).",
1841                    obj=cls,
1842                    id="models.E014",
1843                )
1844            ]
1845
1846        errors = []
1847        fields = cls._meta.ordering
1848
1849        # Skip expressions and '?' fields.
1850        fields = (f for f in fields if isinstance(f, str) and f != "?")
1851
1852        # Convert "-field" to "field".
1853        fields = (f.removeprefix("-") for f in fields)
1854
1855        # Separate related fields and non-related fields.
1856        _fields = []
1857        related_fields = []
1858        for f in fields:
1859            if LOOKUP_SEP in f:
1860                related_fields.append(f)
1861            else:
1862                _fields.append(f)
1863        fields = _fields
1864
1865        # Check related fields.
1866        for field in related_fields:
1867            _cls = cls
1868            fld = None
1869            for part in field.split(LOOKUP_SEP):
1870                try:
1871                    # pk is an alias that won't be found by opts.get_field.
1872                    if part == "pk":
1873                        fld = _cls._meta.pk
1874                    else:
1875                        fld = _cls._meta.get_field(part)
1876                    if fld.is_relation:
1877                        _cls = fld.path_infos[-1].to_opts.model
1878                    else:
1879                        _cls = None
1880                except (FieldDoesNotExist, AttributeError):
1881                    if fld is None or (
1882                        fld.get_transform(part) is None and fld.get_lookup(part) is None
1883                    ):
1884                        errors.append(
1885                            preflight.Error(
1886                                "'ordering' refers to the nonexistent field, "
1887                                "related field, or lookup '%s'." % field,
1888                                obj=cls,
1889                                id="models.E015",
1890                            )
1891                        )
1892
1893        # Skip ordering on pk. This is always a valid order_by field
1894        # but is an alias and therefore won't be found by opts.get_field.
1895        fields = {f for f in fields if f != "pk"}
1896
1897        # Check for invalid or nonexistent fields in ordering.
1898        invalid_fields = []
1899
1900        # Any field name that is not present in field_names does not exist.
1901        # Also, ordering by m2m fields is not allowed.
1902        opts = cls._meta
1903        valid_fields = set(
1904            chain.from_iterable(
1905                (f.name, f.attname)
1906                if not (f.auto_created and not f.concrete)
1907                else (f.field.related_query_name(),)
1908                for f in chain(opts.fields, opts.related_objects)
1909            )
1910        )
1911
1912        invalid_fields.extend(fields - valid_fields)
1913
1914        for invalid_field in invalid_fields:
1915            errors.append(
1916                preflight.Error(
1917                    "'ordering' refers to the nonexistent field, related "
1918                    "field, or lookup '%s'." % invalid_field,
1919                    obj=cls,
1920                    id="models.E015",
1921                )
1922            )
1923        return errors
1924
1925    @classmethod
1926    def _check_long_column_names(cls, databases):
1927        """
1928        Check that any auto-generated column names are shorter than the limits
1929        for each database in which the model will be created.
1930        """
1931        if not databases:
1932            return []
1933        errors = []
1934        allowed_len = None
1935        db_alias = None
1936
1937        # Find the minimum max allowed length among all specified db_aliases.
1938        for db in databases:
1939            # skip databases where the model won't be created
1940            if not router.allow_migrate_model(db, cls):
1941                continue
1942            connection = connections[db]
1943            max_name_length = connection.ops.max_name_length()
1944            if max_name_length is None or connection.features.truncates_names:
1945                continue
1946            else:
1947                if allowed_len is None:
1948                    allowed_len = max_name_length
1949                    db_alias = db
1950                elif max_name_length < allowed_len:
1951                    allowed_len = max_name_length
1952                    db_alias = db
1953
1954        if allowed_len is None:
1955            return errors
1956
1957        for f in cls._meta.local_fields:
1958            _, column_name = f.get_attname_column()
1959
1960            # Check if auto-generated name for the field is too long
1961            # for the database.
1962            if (
1963                f.db_column is None
1964                and column_name is not None
1965                and len(column_name) > allowed_len
1966            ):
1967                errors.append(
1968                    preflight.Error(
1969                        'Autogenerated column name too long for field "{}". '
1970                        'Maximum length is "{}" for database "{}".'.format(
1971                            column_name, allowed_len, db_alias
1972                        ),
1973                        hint="Set the column name manually using 'db_column'.",
1974                        obj=cls,
1975                        id="models.E018",
1976                    )
1977                )
1978
1979        for f in cls._meta.local_many_to_many:
1980            # Skip nonexistent models.
1981            if isinstance(f.remote_field.through, str):
1982                continue
1983
1984            # Check if auto-generated name for the M2M field is too long
1985            # for the database.
1986            for m2m in f.remote_field.through._meta.local_fields:
1987                _, rel_name = m2m.get_attname_column()
1988                if (
1989                    m2m.db_column is None
1990                    and rel_name is not None
1991                    and len(rel_name) > allowed_len
1992                ):
1993                    errors.append(
1994                        preflight.Error(
1995                            "Autogenerated column name too long for M2M field "
1996                            '"{}". Maximum length is "{}" for database "{}".'.format(
1997                                rel_name, allowed_len, db_alias
1998                            ),
1999                            hint=(
2000                                "Use 'through' to create a separate model for "
2001                                "M2M and then set column_name using 'db_column'."
2002                            ),
2003                            obj=cls,
2004                            id="models.E019",
2005                        )
2006                    )
2007
2008        return errors
2009
2010    @classmethod
2011    def _get_expr_references(cls, expr):
2012        if isinstance(expr, Q):
2013            for child in expr.children:
2014                if isinstance(child, tuple):
2015                    lookup, value = child
2016                    yield tuple(lookup.split(LOOKUP_SEP))
2017                    yield from cls._get_expr_references(value)
2018                else:
2019                    yield from cls._get_expr_references(child)
2020        elif isinstance(expr, F):
2021            yield tuple(expr.name.split(LOOKUP_SEP))
2022        elif hasattr(expr, "get_source_expressions"):
2023            for src_expr in expr.get_source_expressions():
2024                yield from cls._get_expr_references(src_expr)
2025
2026    @classmethod
2027    def _check_constraints(cls, databases):
2028        errors = []
2029        for db in databases:
2030            if not router.allow_migrate_model(db, cls):
2031                continue
2032            connection = connections[db]
2033            if not (
2034                connection.features.supports_table_check_constraints
2035                or "supports_table_check_constraints" in cls._meta.required_db_features
2036            ) and any(
2037                isinstance(constraint, CheckConstraint)
2038                for constraint in cls._meta.constraints
2039            ):
2040                errors.append(
2041                    preflight.Warning(
2042                        "%s does not support check constraints."
2043                        % connection.display_name,
2044                        hint=(
2045                            "A constraint won't be created. Silence this "
2046                            "warning if you don't care about it."
2047                        ),
2048                        obj=cls,
2049                        id="models.W027",
2050                    )
2051                )
2052            if not (
2053                connection.features.supports_partial_indexes
2054                or "supports_partial_indexes" in cls._meta.required_db_features
2055            ) and any(
2056                isinstance(constraint, UniqueConstraint)
2057                and constraint.condition is not None
2058                for constraint in cls._meta.constraints
2059            ):
2060                errors.append(
2061                    preflight.Warning(
2062                        "%s does not support unique constraints with "
2063                        "conditions." % connection.display_name,
2064                        hint=(
2065                            "A constraint won't be created. Silence this "
2066                            "warning if you don't care about it."
2067                        ),
2068                        obj=cls,
2069                        id="models.W036",
2070                    )
2071                )
2072            if not (
2073                connection.features.supports_deferrable_unique_constraints
2074                or "supports_deferrable_unique_constraints"
2075                in cls._meta.required_db_features
2076            ) and any(
2077                isinstance(constraint, UniqueConstraint)
2078                and constraint.deferrable is not None
2079                for constraint in cls._meta.constraints
2080            ):
2081                errors.append(
2082                    preflight.Warning(
2083                        "%s does not support deferrable unique constraints."
2084                        % connection.display_name,
2085                        hint=(
2086                            "A constraint won't be created. Silence this "
2087                            "warning if you don't care about it."
2088                        ),
2089                        obj=cls,
2090                        id="models.W038",
2091                    )
2092                )
2093            if not (
2094                connection.features.supports_covering_indexes
2095                or "supports_covering_indexes" in cls._meta.required_db_features
2096            ) and any(
2097                isinstance(constraint, UniqueConstraint) and constraint.include
2098                for constraint in cls._meta.constraints
2099            ):
2100                errors.append(
2101                    preflight.Warning(
2102                        "%s does not support unique constraints with non-key "
2103                        "columns." % connection.display_name,
2104                        hint=(
2105                            "A constraint won't be created. Silence this "
2106                            "warning if you don't care about it."
2107                        ),
2108                        obj=cls,
2109                        id="models.W039",
2110                    )
2111                )
2112            if not (
2113                connection.features.supports_expression_indexes
2114                or "supports_expression_indexes" in cls._meta.required_db_features
2115            ) and any(
2116                isinstance(constraint, UniqueConstraint)
2117                and constraint.contains_expressions
2118                for constraint in cls._meta.constraints
2119            ):
2120                errors.append(
2121                    preflight.Warning(
2122                        "%s does not support unique constraints on "
2123                        "expressions." % connection.display_name,
2124                        hint=(
2125                            "A constraint won't be created. Silence this "
2126                            "warning if you don't care about it."
2127                        ),
2128                        obj=cls,
2129                        id="models.W044",
2130                    )
2131                )
2132            fields = set(
2133                chain.from_iterable(
2134                    (*constraint.fields, *constraint.include)
2135                    for constraint in cls._meta.constraints
2136                    if isinstance(constraint, UniqueConstraint)
2137                )
2138            )
2139            references = set()
2140            for constraint in cls._meta.constraints:
2141                if isinstance(constraint, UniqueConstraint):
2142                    if (
2143                        connection.features.supports_partial_indexes
2144                        or "supports_partial_indexes"
2145                        not in cls._meta.required_db_features
2146                    ) and isinstance(constraint.condition, Q):
2147                        references.update(
2148                            cls._get_expr_references(constraint.condition)
2149                        )
2150                    if (
2151                        connection.features.supports_expression_indexes
2152                        or "supports_expression_indexes"
2153                        not in cls._meta.required_db_features
2154                    ) and constraint.contains_expressions:
2155                        for expression in constraint.expressions:
2156                            references.update(cls._get_expr_references(expression))
2157                elif isinstance(constraint, CheckConstraint):
2158                    if (
2159                        connection.features.supports_table_check_constraints
2160                        or "supports_table_check_constraints"
2161                        not in cls._meta.required_db_features
2162                    ):
2163                        if isinstance(constraint.check, Q):
2164                            references.update(
2165                                cls._get_expr_references(constraint.check)
2166                            )
2167                        if any(
2168                            isinstance(expr, RawSQL)
2169                            for expr in constraint.check.flatten()
2170                        ):
2171                            errors.append(
2172                                preflight.Warning(
2173                                    f"Check constraint {constraint.name!r} contains "
2174                                    f"RawSQL() expression and won't be validated "
2175                                    f"during the model full_clean().",
2176                                    hint=(
2177                                        "Silence this warning if you don't care about "
2178                                        "it."
2179                                    ),
2180                                    obj=cls,
2181                                    id="models.W045",
2182                                ),
2183                            )
2184            for field_name, *lookups in references:
2185                # pk is an alias that won't be found by opts.get_field.
2186                if field_name != "pk":
2187                    fields.add(field_name)
2188                if not lookups:
2189                    # If it has no lookups it cannot result in a JOIN.
2190                    continue
2191                try:
2192                    if field_name == "pk":
2193                        field = cls._meta.pk
2194                    else:
2195                        field = cls._meta.get_field(field_name)
2196                    if not field.is_relation or field.many_to_many or field.one_to_many:
2197                        continue
2198                except FieldDoesNotExist:
2199                    continue
2200                # JOIN must happen at the first lookup.
2201                first_lookup = lookups[0]
2202                if (
2203                    hasattr(field, "get_transform")
2204                    and hasattr(field, "get_lookup")
2205                    and field.get_transform(first_lookup) is None
2206                    and field.get_lookup(first_lookup) is None
2207                ):
2208                    errors.append(
2209                        preflight.Error(
2210                            "'constraints' refers to the joined field '%s'."
2211                            % LOOKUP_SEP.join([field_name] + lookups),
2212                            obj=cls,
2213                            id="models.E041",
2214                        )
2215                    )
2216            errors.extend(cls._check_local_fields(fields, "constraints"))
2217        return errors
2218
2219
2220############################################
2221# HELPER FUNCTIONS (CURRIED MODEL METHODS) #
2222############################################
2223
2224# ORDERING METHODS #########################
2225
2226
2227def method_set_order(self, ordered_obj, id_list, using=None):
2228    order_wrt = ordered_obj._meta.order_with_respect_to
2229    filter_args = order_wrt.get_forward_related_filter(self)
2230    ordered_obj.objects.db_manager(using).filter(**filter_args).bulk_update(
2231        [ordered_obj(pk=pk, _order=order) for order, pk in enumerate(id_list)],
2232        ["_order"],
2233    )
2234
2235
2236def method_get_order(self, ordered_obj):
2237    order_wrt = ordered_obj._meta.order_with_respect_to
2238    filter_args = order_wrt.get_forward_related_filter(self)
2239    pk_name = ordered_obj._meta.pk.name
2240    return ordered_obj.objects.filter(**filter_args).values_list(pk_name, flat=True)
2241
2242
2243def make_foreign_order_accessors(model, related_model):
2244    setattr(
2245        related_model,
2246        "get_%s_order" % model.__name__.lower(),
2247        partialmethod(method_get_order, model),
2248    )
2249    setattr(
2250        related_model,
2251        "set_%s_order" % model.__name__.lower(),
2252        partialmethod(method_set_order, model),
2253    )
2254
2255
2256########
2257# MISC #
2258########
2259
2260
2261def model_unpickle(model_id):
2262    """Used to unpickle Model subclasses with deferred fields."""
2263    if isinstance(model_id, tuple):
2264        model = packages.get_model(*model_id)
2265    else:
2266        # Backwards compat - the model was cached directly in earlier versions.
2267        model = model_id
2268    return model.__new__(model)
2269
2270
2271model_unpickle.__safe_for_unpickle__ = True