Plain is headed towards 1.0! Subscribe for development updates →

   1import collections.abc
   2import copy
   3import datetime
   4import decimal
   5import operator
   6import uuid
   7import warnings
   8from base64 import b64decode, b64encode
   9from functools import partialmethod, total_ordering
  10
  11from plain import exceptions, preflight, validators
  12from plain.models.constants import LOOKUP_SEP
  13from plain.models.db import connection, connections, router
  14from plain.models.enums import ChoicesMeta
  15from plain.models.query_utils import DeferredAttribute, RegisterLookupMixin
  16from plain.packages import packages
  17from plain.runtime import settings
  18from plain.utils import timezone
  19from plain.utils.datastructures import DictWrapper
  20from plain.utils.dateparse import (
  21    parse_date,
  22    parse_datetime,
  23    parse_duration,
  24    parse_time,
  25)
  26from plain.utils.duration import duration_microseconds, duration_string
  27from plain.utils.functional import Promise, cached_property
  28from plain.utils.ipv6 import clean_ipv6_address
  29from plain.utils.itercompat import is_iterable
  30
  31__all__ = [
  32    "AutoField",
  33    "BLANK_CHOICE_DASH",
  34    "BigAutoField",
  35    "BigIntegerField",
  36    "BinaryField",
  37    "BooleanField",
  38    "CharField",
  39    "CommaSeparatedIntegerField",
  40    "DateField",
  41    "DateTimeField",
  42    "DecimalField",
  43    "DurationField",
  44    "EmailField",
  45    "Empty",
  46    "Field",
  47    "FloatField",
  48    "GenericIPAddressField",
  49    "IPAddressField",
  50    "IntegerField",
  51    "NOT_PROVIDED",
  52    "NullBooleanField",
  53    "PositiveBigIntegerField",
  54    "PositiveIntegerField",
  55    "PositiveSmallIntegerField",
  56    "SlugField",
  57    "SmallAutoField",
  58    "SmallIntegerField",
  59    "TextField",
  60    "TimeField",
  61    "URLField",
  62    "UUIDField",
  63]
  64
  65
  66class Empty:
  67    pass
  68
  69
  70class NOT_PROVIDED:
  71    pass
  72
  73
  74# The values to use for "blank" in SelectFields. Will be appended to the start
  75# of most "choices" lists.
  76BLANK_CHOICE_DASH = [("", "---------")]
  77
  78
  79def _load_field(package_label, model_name, field_name):
  80    return packages.get_model(package_label, model_name)._meta.get_field(field_name)
  81
  82
  83# A guide to Field parameters:
  84#
  85#   * name:      The name of the field specified in the model.
  86#   * attname:   The attribute to use on the model object. This is the same as
  87#                "name", except in the case of ForeignKeys, where "_id" is
  88#                appended.
  89#   * db_column: The db_column specified in the model (or None).
  90#   * column:    The database column for this field. This is the same as
  91#                "attname", except if db_column is specified.
  92#
  93# Code that introspects values, or does other dynamic things, should use
  94# attname. For example, this gets the primary key value of object "obj":
  95#
  96#     getattr(obj, opts.pk.attname)
  97
  98
  99def _empty(of_cls):
 100    new = Empty()
 101    new.__class__ = of_cls
 102    return new
 103
 104
 105def return_None():
 106    return None
 107
 108
 109@total_ordering
 110class Field(RegisterLookupMixin):
 111    """Base class for all field types"""
 112
 113    # Designates whether empty strings fundamentally are allowed at the
 114    # database level.
 115    empty_strings_allowed = True
 116    empty_values = list(validators.EMPTY_VALUES)
 117
 118    # These track each time a Field instance is created. Used to retain order.
 119    # The auto_creation_counter is used for fields that Plain implicitly
 120    # creates, creation_counter is used for all user-specified fields.
 121    creation_counter = 0
 122    auto_creation_counter = -1
 123    default_validators = []  # Default set of validators
 124    default_error_messages = {
 125        "invalid_choice": "Value %(value)r is not a valid choice.",
 126        "null": "This field cannot be null.",
 127        "blank": "This field cannot be blank.",
 128        "unique": "A %(model_name)s with this %(field_label)s already exists.",
 129    }
 130    system_check_deprecated_details = None
 131    system_check_removed_details = None
 132
 133    # Attributes that don't affect a column definition.
 134    # These attributes are ignored when altering the field.
 135    non_db_attrs = (
 136        "blank",
 137        "choices",
 138        "db_column",
 139        "editable",
 140        "error_messages",
 141        "limit_choices_to",
 142        # Database-level options are not supported, see #21961.
 143        "on_delete",
 144        "related_name",
 145        "related_query_name",
 146        "validators",
 147    )
 148
 149    # Field flags
 150    hidden = False
 151
 152    many_to_many = None
 153    many_to_one = None
 154    one_to_many = None
 155    one_to_one = None
 156    related_model = None
 157
 158    descriptor_class = DeferredAttribute
 159
 160    # Generic field type description, usually overridden by subclasses
 161    def _description(self):
 162        return f"Field of type: {self.__class__.__name__}"
 163
 164    description = property(_description)
 165
 166    def __init__(
 167        self,
 168        name=None,
 169        primary_key=False,
 170        max_length=None,
 171        unique=False,
 172        blank=False,
 173        null=False,
 174        db_index=False,
 175        rel=None,
 176        default=NOT_PROVIDED,
 177        editable=True,
 178        choices=None,
 179        db_column=None,
 180        db_tablespace=None,
 181        auto_created=False,
 182        validators=(),
 183        error_messages=None,
 184        db_comment=None,
 185    ):
 186        self.name = name
 187        self.primary_key = primary_key
 188        self.max_length, self._unique = max_length, unique
 189        self.blank, self.null = blank, null
 190        self.remote_field = rel
 191        self.is_relation = self.remote_field is not None
 192        self.default = default
 193        self.editable = editable
 194        if isinstance(choices, ChoicesMeta):
 195            choices = choices.choices
 196        if isinstance(choices, collections.abc.Iterator):
 197            choices = list(choices)
 198        self.choices = choices
 199        self.db_index = db_index
 200        self.db_column = db_column
 201        self.db_comment = db_comment
 202        self._db_tablespace = db_tablespace
 203        self.auto_created = auto_created
 204
 205        # Adjust the appropriate creation counter, and save our local copy.
 206        if auto_created:
 207            self.creation_counter = Field.auto_creation_counter
 208            Field.auto_creation_counter -= 1
 209        else:
 210            self.creation_counter = Field.creation_counter
 211            Field.creation_counter += 1
 212
 213        self._validators = list(validators)  # Store for deconstruction later
 214
 215        self._error_messages = error_messages  # Store for deconstruction later
 216
 217    def __str__(self):
 218        """
 219        Return "package_label.model_label.field_name" for fields attached to
 220        models.
 221        """
 222        if not hasattr(self, "model"):
 223            return super().__str__()
 224        model = self.model
 225        return f"{model._meta.label}.{self.name}"
 226
 227    def __repr__(self):
 228        """Display the module, class, and name of the field."""
 229        path = f"{self.__class__.__module__}.{self.__class__.__qualname__}"
 230        name = getattr(self, "name", None)
 231        if name is not None:
 232            return f"<{path}: {name}>"
 233        return "<%s>" % path
 234
 235    def check(self, **kwargs):
 236        return [
 237            *self._check_field_name(),
 238            *self._check_choices(),
 239            *self._check_db_index(),
 240            *self._check_db_comment(**kwargs),
 241            *self._check_null_allowed_for_primary_keys(),
 242            *self._check_backend_specific_checks(**kwargs),
 243            *self._check_validators(),
 244            *self._check_deprecation_details(),
 245        ]
 246
 247    def _check_field_name(self):
 248        """
 249        Check if field name is valid, i.e. 1) does not end with an
 250        underscore, 2) does not contain "__" and 3) is not "pk".
 251        """
 252        if self.name.endswith("_"):
 253            return [
 254                preflight.Error(
 255                    "Field names must not end with an underscore.",
 256                    obj=self,
 257                    id="fields.E001",
 258                )
 259            ]
 260        elif LOOKUP_SEP in self.name:
 261            return [
 262                preflight.Error(
 263                    'Field names must not contain "%s".' % LOOKUP_SEP,
 264                    obj=self,
 265                    id="fields.E002",
 266                )
 267            ]
 268        elif self.name == "pk":
 269            return [
 270                preflight.Error(
 271                    "'pk' is a reserved word that cannot be used as a field name.",
 272                    obj=self,
 273                    id="fields.E003",
 274                )
 275            ]
 276        else:
 277            return []
 278
 279    @classmethod
 280    def _choices_is_value(cls, value):
 281        return isinstance(value, str | Promise) or not is_iterable(value)
 282
 283    def _check_choices(self):
 284        if not self.choices:
 285            return []
 286
 287        if not is_iterable(self.choices) or isinstance(self.choices, str):
 288            return [
 289                preflight.Error(
 290                    "'choices' must be an iterable (e.g., a list or tuple).",
 291                    obj=self,
 292                    id="fields.E004",
 293                )
 294            ]
 295
 296        choice_max_length = 0
 297        # Expect [group_name, [value, display]]
 298        for choices_group in self.choices:
 299            try:
 300                group_name, group_choices = choices_group
 301            except (TypeError, ValueError):
 302                # Containing non-pairs
 303                break
 304            try:
 305                if not all(
 306                    self._choices_is_value(value) and self._choices_is_value(human_name)
 307                    for value, human_name in group_choices
 308                ):
 309                    break
 310                if self.max_length is not None and group_choices:
 311                    choice_max_length = max(
 312                        [
 313                            choice_max_length,
 314                            *(
 315                                len(value)
 316                                for value, _ in group_choices
 317                                if isinstance(value, str)
 318                            ),
 319                        ]
 320                    )
 321            except (TypeError, ValueError):
 322                # No groups, choices in the form [value, display]
 323                value, human_name = group_name, group_choices
 324                if not self._choices_is_value(value) or not self._choices_is_value(
 325                    human_name
 326                ):
 327                    break
 328                if self.max_length is not None and isinstance(value, str):
 329                    choice_max_length = max(choice_max_length, len(value))
 330
 331            # Special case: choices=['ab']
 332            if isinstance(choices_group, str):
 333                break
 334        else:
 335            if self.max_length is not None and choice_max_length > self.max_length:
 336                return [
 337                    preflight.Error(
 338                        "'max_length' is too small to fit the longest value "
 339                        "in 'choices' (%d characters)." % choice_max_length,
 340                        obj=self,
 341                        id="fields.E009",
 342                    ),
 343                ]
 344            return []
 345
 346        return [
 347            preflight.Error(
 348                "'choices' must be an iterable containing "
 349                "(actual value, human readable name) tuples.",
 350                obj=self,
 351                id="fields.E005",
 352            )
 353        ]
 354
 355    def _check_db_index(self):
 356        if self.db_index not in (None, True, False):
 357            return [
 358                preflight.Error(
 359                    "'db_index' must be None, True or False.",
 360                    obj=self,
 361                    id="fields.E006",
 362                )
 363            ]
 364        else:
 365            return []
 366
 367    def _check_db_comment(self, databases=None, **kwargs):
 368        if not self.db_comment or not databases:
 369            return []
 370        errors = []
 371        for db in databases:
 372            if not router.allow_migrate_model(db, self.model):
 373                continue
 374            connection = connections[db]
 375            if not (
 376                connection.features.supports_comments
 377                or "supports_comments" in self.model._meta.required_db_features
 378            ):
 379                errors.append(
 380                    preflight.Warning(
 381                        f"{connection.display_name} does not support comments on "
 382                        f"columns (db_comment).",
 383                        obj=self,
 384                        id="fields.W163",
 385                    )
 386                )
 387        return errors
 388
 389    def _check_null_allowed_for_primary_keys(self):
 390        if (
 391            self.primary_key
 392            and self.null
 393            and not connection.features.interprets_empty_strings_as_nulls
 394        ):
 395            # We cannot reliably check this for backends like Oracle which
 396            # consider NULL and '' to be equal (and thus set up
 397            # character-based fields a little differently).
 398            return [
 399                preflight.Error(
 400                    "Primary keys must not have null=True.",
 401                    hint=(
 402                        "Set null=False on the field, or "
 403                        "remove primary_key=True argument."
 404                    ),
 405                    obj=self,
 406                    id="fields.E007",
 407                )
 408            ]
 409        else:
 410            return []
 411
 412    def _check_backend_specific_checks(self, databases=None, **kwargs):
 413        if databases is None:
 414            return []
 415        errors = []
 416        for alias in databases:
 417            if router.allow_migrate_model(alias, self.model):
 418                errors.extend(connections[alias].validation.check_field(self, **kwargs))
 419        return errors
 420
 421    def _check_validators(self):
 422        errors = []
 423        for i, validator in enumerate(self.validators):
 424            if not callable(validator):
 425                errors.append(
 426                    preflight.Error(
 427                        "All 'validators' must be callable.",
 428                        hint=(
 429                            f"validators[{i}] ({repr(validator)}) isn't a function or "
 430                            "instance of a validator class."
 431                        ),
 432                        obj=self,
 433                        id="fields.E008",
 434                    )
 435                )
 436        return errors
 437
 438    def _check_deprecation_details(self):
 439        if self.system_check_removed_details is not None:
 440            return [
 441                preflight.Error(
 442                    self.system_check_removed_details.get(
 443                        "msg",
 444                        "%s has been removed except for support in historical "
 445                        "migrations." % self.__class__.__name__,
 446                    ),
 447                    hint=self.system_check_removed_details.get("hint"),
 448                    obj=self,
 449                    id=self.system_check_removed_details.get("id", "fields.EXXX"),
 450                )
 451            ]
 452        elif self.system_check_deprecated_details is not None:
 453            return [
 454                preflight.Warning(
 455                    self.system_check_deprecated_details.get(
 456                        "msg", "%s has been deprecated." % self.__class__.__name__
 457                    ),
 458                    hint=self.system_check_deprecated_details.get("hint"),
 459                    obj=self,
 460                    id=self.system_check_deprecated_details.get("id", "fields.WXXX"),
 461                )
 462            ]
 463        return []
 464
 465    def get_col(self, alias, output_field=None):
 466        if alias == self.model._meta.db_table and (
 467            output_field is None or output_field == self
 468        ):
 469            return self.cached_col
 470        from plain.models.expressions import Col
 471
 472        return Col(alias, self, output_field)
 473
 474    @cached_property
 475    def cached_col(self):
 476        from plain.models.expressions import Col
 477
 478        return Col(self.model._meta.db_table, self)
 479
 480    def select_format(self, compiler, sql, params):
 481        """
 482        Custom format for select clauses. For example, GIS columns need to be
 483        selected as AsText(table.col) on MySQL as the table.col data can't be
 484        used by Plain.
 485        """
 486        return sql, params
 487
 488    def deconstruct(self):
 489        """
 490        Return enough information to recreate the field as a 4-tuple:
 491
 492         * The name of the field on the model, if contribute_to_class() has
 493           been run.
 494         * The import path of the field, including the class, e.g.
 495           plain.models.IntegerField. This should be the most portable
 496           version, so less specific may be better.
 497         * A list of positional arguments.
 498         * A dict of keyword arguments.
 499
 500        Note that the positional or keyword arguments must contain values of
 501        the following types (including inner values of collection types):
 502
 503         * None, bool, str, int, float, complex, set, frozenset, list, tuple,
 504           dict
 505         * UUID
 506         * datetime.datetime (naive), datetime.date
 507         * top-level classes, top-level functions - will be referenced by their
 508           full import path
 509         * Storage instances - these have their own deconstruct() method
 510
 511        This is because the values here must be serialized into a text format
 512        (possibly new Python code, possibly JSON) and these are the only types
 513        with encoding handlers defined.
 514
 515        There's no need to return the exact way the field was instantiated this
 516        time, just ensure that the resulting field is the same - prefer keyword
 517        arguments over positional ones, and omit parameters with their default
 518        values.
 519        """
 520        # Short-form way of fetching all the default parameters
 521        keywords = {}
 522        possibles = {
 523            "primary_key": False,
 524            "max_length": None,
 525            "unique": False,
 526            "blank": False,
 527            "null": False,
 528            "db_index": False,
 529            "default": NOT_PROVIDED,
 530            "editable": True,
 531            "choices": None,
 532            "db_column": None,
 533            "db_comment": None,
 534            "db_tablespace": None,
 535            "auto_created": False,
 536            "validators": [],
 537            "error_messages": None,
 538        }
 539        attr_overrides = {
 540            "unique": "_unique",
 541            "error_messages": "_error_messages",
 542            "validators": "_validators",
 543            "db_tablespace": "_db_tablespace",
 544        }
 545        equals_comparison = {"choices", "validators"}
 546        for name, default in possibles.items():
 547            value = getattr(self, attr_overrides.get(name, name))
 548            # Unroll anything iterable for choices into a concrete list
 549            if name == "choices" and isinstance(value, collections.abc.Iterable):
 550                value = list(value)
 551            # Do correct kind of comparison
 552            if name in equals_comparison:
 553                if value != default:
 554                    keywords[name] = value
 555            else:
 556                if value is not default:
 557                    keywords[name] = value
 558        # Work out path - we shorten it for known Plain core fields
 559        path = f"{self.__class__.__module__}.{self.__class__.__qualname__}"
 560        if path.startswith("plain.models.fields.related"):
 561            path = path.replace("plain.models.fields.related", "plain.models")
 562        elif path.startswith("plain.models.fields.json"):
 563            path = path.replace("plain.models.fields.json", "plain.models")
 564        elif path.startswith("plain.models.fields.proxy"):
 565            path = path.replace("plain.models.fields.proxy", "plain.models")
 566        elif path.startswith("plain.models.fields"):
 567            path = path.replace("plain.models.fields", "plain.models")
 568        # Return basic info - other fields should override this.
 569        return (self.name, path, [], keywords)
 570
 571    def clone(self):
 572        """
 573        Uses deconstruct() to clone a new copy of this Field.
 574        Will not preserve any class attachments/attribute names.
 575        """
 576        name, path, args, kwargs = self.deconstruct()
 577        return self.__class__(*args, **kwargs)
 578
 579    def __eq__(self, other):
 580        # Needed for @total_ordering
 581        if isinstance(other, Field):
 582            return self.creation_counter == other.creation_counter and getattr(
 583                self, "model", None
 584            ) == getattr(other, "model", None)
 585        return NotImplemented
 586
 587    def __lt__(self, other):
 588        # This is needed because bisect does not take a comparison function.
 589        # Order by creation_counter first for backward compatibility.
 590        if isinstance(other, Field):
 591            if (
 592                self.creation_counter != other.creation_counter
 593                or not hasattr(self, "model")
 594                and not hasattr(other, "model")
 595            ):
 596                return self.creation_counter < other.creation_counter
 597            elif hasattr(self, "model") != hasattr(other, "model"):
 598                return not hasattr(self, "model")  # Order no-model fields first
 599            else:
 600                # creation_counter's are equal, compare only models.
 601                return (self.model._meta.package_label, self.model._meta.model_name) < (
 602                    other.model._meta.package_label,
 603                    other.model._meta.model_name,
 604                )
 605        return NotImplemented
 606
 607    def __hash__(self):
 608        return hash(self.creation_counter)
 609
 610    def __deepcopy__(self, memodict):
 611        # We don't have to deepcopy very much here, since most things are not
 612        # intended to be altered after initial creation.
 613        obj = copy.copy(self)
 614        if self.remote_field:
 615            obj.remote_field = copy.copy(self.remote_field)
 616            if hasattr(self.remote_field, "field") and self.remote_field.field is self:
 617                obj.remote_field.field = obj
 618        memodict[id(self)] = obj
 619        return obj
 620
 621    def __copy__(self):
 622        # We need to avoid hitting __reduce__, so define this
 623        # slightly weird copy construct.
 624        obj = Empty()
 625        obj.__class__ = self.__class__
 626        obj.__dict__ = self.__dict__.copy()
 627        return obj
 628
 629    def __reduce__(self):
 630        """
 631        Pickling should return the model._meta.fields instance of the field,
 632        not a new copy of that field. So, use the app registry to load the
 633        model and then the field back.
 634        """
 635        if not hasattr(self, "model"):
 636            # Fields are sometimes used without attaching them to models (for
 637            # example in aggregation). In this case give back a plain field
 638            # instance. The code below will create a new empty instance of
 639            # class self.__class__, then update its dict with self.__dict__
 640            # values - so, this is very close to normal pickle.
 641            state = self.__dict__.copy()
 642            # The _get_default cached_property can't be pickled due to lambda
 643            # usage.
 644            state.pop("_get_default", None)
 645            return _empty, (self.__class__,), state
 646        return _load_field, (
 647            self.model._meta.package_label,
 648            self.model._meta.object_name,
 649            self.name,
 650        )
 651
 652    def get_pk_value_on_save(self, instance):
 653        """
 654        Hook to generate new PK values on save. This method is called when
 655        saving instances with no primary key value set. If this method returns
 656        something else than None, then the returned value is used when saving
 657        the new instance.
 658        """
 659        if self.default:
 660            return self.get_default()
 661        return None
 662
 663    def to_python(self, value):
 664        """
 665        Convert the input value into the expected Python data type, raising
 666        plain.exceptions.ValidationError if the data can't be converted.
 667        Return the converted value. Subclasses should override this.
 668        """
 669        return value
 670
 671    @cached_property
 672    def error_messages(self):
 673        messages = {}
 674        for c in reversed(self.__class__.__mro__):
 675            messages.update(getattr(c, "default_error_messages", {}))
 676        messages.update(self._error_messages or {})
 677        return messages
 678
 679    @cached_property
 680    def validators(self):
 681        """
 682        Some validators can't be created at field initialization time.
 683        This method provides a way to delay their creation until required.
 684        """
 685        return [*self.default_validators, *self._validators]
 686
 687    def run_validators(self, value):
 688        if value in self.empty_values:
 689            return
 690
 691        errors = []
 692        for v in self.validators:
 693            try:
 694                v(value)
 695            except exceptions.ValidationError as e:
 696                if hasattr(e, "code") and e.code in self.error_messages:
 697                    e.message = self.error_messages[e.code]
 698                errors.extend(e.error_list)
 699
 700        if errors:
 701            raise exceptions.ValidationError(errors)
 702
 703    def validate(self, value, model_instance):
 704        """
 705        Validate value and raise ValidationError if necessary. Subclasses
 706        should override this to provide validation logic.
 707        """
 708        if not self.editable:
 709            # Skip validation for non-editable fields.
 710            return
 711
 712        if self.choices is not None and value not in self.empty_values:
 713            for option_key, option_value in self.choices:
 714                if isinstance(option_value, list | tuple):
 715                    # This is an optgroup, so look inside the group for
 716                    # options.
 717                    for optgroup_key, optgroup_value in option_value:
 718                        if value == optgroup_key:
 719                            return
 720                elif value == option_key:
 721                    return
 722            raise exceptions.ValidationError(
 723                self.error_messages["invalid_choice"],
 724                code="invalid_choice",
 725                params={"value": value},
 726            )
 727
 728        if value is None and not self.null:
 729            raise exceptions.ValidationError(self.error_messages["null"], code="null")
 730
 731        if not self.blank and value in self.empty_values:
 732            raise exceptions.ValidationError(self.error_messages["blank"], code="blank")
 733
 734    def clean(self, value, model_instance):
 735        """
 736        Convert the value's type and run validation. Validation errors
 737        from to_python() and validate() are propagated. Return the correct
 738        value if no error is raised.
 739        """
 740        value = self.to_python(value)
 741        self.validate(value, model_instance)
 742        self.run_validators(value)
 743        return value
 744
 745    def db_type_parameters(self, connection):
 746        return DictWrapper(self.__dict__, connection.ops.quote_name, "qn_")
 747
 748    def db_check(self, connection):
 749        """
 750        Return the database column check constraint for this field, for the
 751        provided connection. Works the same way as db_type() for the case that
 752        get_internal_type() does not map to a preexisting model field.
 753        """
 754        data = self.db_type_parameters(connection)
 755        try:
 756            return (
 757                connection.data_type_check_constraints[self.get_internal_type()] % data
 758            )
 759        except KeyError:
 760            return None
 761
 762    def db_type(self, connection):
 763        """
 764        Return the database column data type for this field, for the provided
 765        connection.
 766        """
 767        # The default implementation of this method looks at the
 768        # backend-specific data_types dictionary, looking up the field by its
 769        # "internal type".
 770        #
 771        # A Field class can implement the get_internal_type() method to specify
 772        # which *preexisting* Plain Field class it's most similar to -- i.e.,
 773        # a custom field might be represented by a TEXT column type, which is
 774        # the same as the TextField Plain field type, which means the custom
 775        # field's get_internal_type() returns 'TextField'.
 776        #
 777        # But the limitation of the get_internal_type() / data_types approach
 778        # is that it cannot handle database column types that aren't already
 779        # mapped to one of the built-in Plain field types. In this case, you
 780        # can implement db_type() instead of get_internal_type() to specify
 781        # exactly which wacky database column type you want to use.
 782        data = self.db_type_parameters(connection)
 783        try:
 784            column_type = connection.data_types[self.get_internal_type()]
 785        except KeyError:
 786            return None
 787        else:
 788            # column_type is either a single-parameter function or a string.
 789            if callable(column_type):
 790                return column_type(data)
 791            return column_type % data
 792
 793    def rel_db_type(self, connection):
 794        """
 795        Return the data type that a related field pointing to this field should
 796        use. For example, this method is called by ForeignKey and OneToOneField
 797        to determine its data type.
 798        """
 799        return self.db_type(connection)
 800
 801    def cast_db_type(self, connection):
 802        """Return the data type to use in the Cast() function."""
 803        db_type = connection.ops.cast_data_types.get(self.get_internal_type())
 804        if db_type:
 805            return db_type % self.db_type_parameters(connection)
 806        return self.db_type(connection)
 807
 808    def db_parameters(self, connection):
 809        """
 810        Extension of db_type(), providing a range of different return values
 811        (type, checks). This will look at db_type(), allowing custom model
 812        fields to override it.
 813        """
 814        type_string = self.db_type(connection)
 815        check_string = self.db_check(connection)
 816        return {
 817            "type": type_string,
 818            "check": check_string,
 819        }
 820
 821    def db_type_suffix(self, connection):
 822        return connection.data_types_suffix.get(self.get_internal_type())
 823
 824    def get_db_converters(self, connection):
 825        if hasattr(self, "from_db_value"):
 826            return [self.from_db_value]
 827        return []
 828
 829    @property
 830    def unique(self):
 831        return self._unique or self.primary_key
 832
 833    @property
 834    def db_tablespace(self):
 835        return self._db_tablespace or settings.DEFAULT_INDEX_TABLESPACE
 836
 837    @property
 838    def db_returning(self):
 839        """
 840        Private API intended only to be used by Plain itself. Currently only
 841        the PostgreSQL backend supports returning multiple fields on a model.
 842        """
 843        return False
 844
 845    def set_attributes_from_name(self, name):
 846        self.name = self.name or name
 847        self.attname, self.column = self.get_attname_column()
 848        self.concrete = self.column is not None
 849
 850    def contribute_to_class(self, cls, name, private_only=False):
 851        """
 852        Register the field with the model class it belongs to.
 853
 854        If private_only is True, create a separate instance of this field
 855        for every subclass of cls, even if cls is not an abstract model.
 856        """
 857        self.set_attributes_from_name(name)
 858        self.model = cls
 859        cls._meta.add_field(self, private=private_only)
 860        if self.column:
 861            setattr(cls, self.attname, self.descriptor_class(self))
 862        if self.choices is not None:
 863            # Don't override a get_FOO_display() method defined explicitly on
 864            # this class, but don't check methods derived from inheritance, to
 865            # allow overriding inherited choices. For more complex inheritance
 866            # structures users should override contribute_to_class().
 867            if "get_%s_display" % self.name not in cls.__dict__:
 868                setattr(
 869                    cls,
 870                    "get_%s_display" % self.name,
 871                    partialmethod(cls._get_FIELD_display, field=self),
 872                )
 873
 874    def get_filter_kwargs_for_object(self, obj):
 875        """
 876        Return a dict that when passed as kwargs to self.model.filter(), would
 877        yield all instances having the same value for this field as obj has.
 878        """
 879        return {self.name: getattr(obj, self.attname)}
 880
 881    def get_attname(self):
 882        return self.name
 883
 884    def get_attname_column(self):
 885        attname = self.get_attname()
 886        column = self.db_column or attname
 887        return attname, column
 888
 889    def get_internal_type(self):
 890        return self.__class__.__name__
 891
 892    def pre_save(self, model_instance, add):
 893        """Return field's value just before saving."""
 894        return getattr(model_instance, self.attname)
 895
 896    def get_prep_value(self, value):
 897        """Perform preliminary non-db specific value checks and conversions."""
 898        if isinstance(value, Promise):
 899            value = value._proxy____cast()
 900        return value
 901
 902    def get_db_prep_value(self, value, connection, prepared=False):
 903        """
 904        Return field's value prepared for interacting with the database backend.
 905
 906        Used by the default implementations of get_db_prep_save().
 907        """
 908        if not prepared:
 909            value = self.get_prep_value(value)
 910        return value
 911
 912    def get_db_prep_save(self, value, connection):
 913        """Return field's value prepared for saving into a database."""
 914        if hasattr(value, "as_sql"):
 915            return value
 916        return self.get_db_prep_value(value, connection=connection, prepared=False)
 917
 918    def has_default(self):
 919        """Return a boolean of whether this field has a default value."""
 920        return self.default is not NOT_PROVIDED
 921
 922    def get_default(self):
 923        """Return the default value for this field."""
 924        return self._get_default()
 925
 926    @cached_property
 927    def _get_default(self):
 928        if self.has_default():
 929            if callable(self.default):
 930                return self.default
 931            return lambda: self.default
 932
 933        if (
 934            not self.empty_strings_allowed
 935            or self.null
 936            and not connection.features.interprets_empty_strings_as_nulls
 937        ):
 938            return return_None
 939        return str  # return empty string
 940
 941    def get_choices(
 942        self,
 943        include_blank=True,
 944        blank_choice=BLANK_CHOICE_DASH,
 945        limit_choices_to=None,
 946        ordering=(),
 947    ):
 948        """
 949        Return choices with a default blank choices included, for use
 950        as <select> choices for this field.
 951        """
 952        if self.choices is not None:
 953            choices = list(self.choices)
 954            if include_blank:
 955                blank_defined = any(
 956                    choice in ("", None) for choice, _ in self.flatchoices
 957                )
 958                if not blank_defined:
 959                    choices = blank_choice + choices
 960            return choices
 961        rel_model = self.remote_field.model
 962        limit_choices_to = limit_choices_to or self.get_limit_choices_to()
 963        choice_func = operator.attrgetter(
 964            self.remote_field.get_related_field().attname
 965            if hasattr(self.remote_field, "get_related_field")
 966            else "pk"
 967        )
 968        qs = rel_model._default_manager.complex_filter(limit_choices_to)
 969        if ordering:
 970            qs = qs.order_by(*ordering)
 971        return (blank_choice if include_blank else []) + [
 972            (choice_func(x), str(x)) for x in qs
 973        ]
 974
 975    def value_to_string(self, obj):
 976        """
 977        Return a string value of this field from the passed obj.
 978        This is used by the serialization framework.
 979        """
 980        return str(self.value_from_object(obj))
 981
 982    def _get_flatchoices(self):
 983        """Flattened version of choices tuple."""
 984        if self.choices is None:
 985            return []
 986        flat = []
 987        for choice, value in self.choices:
 988            if isinstance(value, list | tuple):
 989                flat.extend(value)
 990            else:
 991                flat.append((choice, value))
 992        return flat
 993
 994    flatchoices = property(_get_flatchoices)
 995
 996    def save_form_data(self, instance, data):
 997        setattr(instance, self.name, data)
 998
 999    def value_from_object(self, obj):
1000        """Return the value of this field in the given model instance."""
1001        return getattr(obj, self.attname)
1002
1003
1004class BooleanField(Field):
1005    empty_strings_allowed = False
1006    default_error_messages = {
1007        "invalid": "“%(value)s” value must be either True or False.",
1008        "invalid_nullable": "“%(value)s” value must be either True, False, or None.",
1009    }
1010    description = "Boolean (Either True or False)"
1011
1012    def get_internal_type(self):
1013        return "BooleanField"
1014
1015    def to_python(self, value):
1016        if self.null and value in self.empty_values:
1017            return None
1018        if value in (True, False):
1019            # 1/0 are equal to True/False. bool() converts former to latter.
1020            return bool(value)
1021        if value in ("t", "True", "1"):
1022            return True
1023        if value in ("f", "False", "0"):
1024            return False
1025        raise exceptions.ValidationError(
1026            self.error_messages["invalid_nullable" if self.null else "invalid"],
1027            code="invalid",
1028            params={"value": value},
1029        )
1030
1031    def get_prep_value(self, value):
1032        value = super().get_prep_value(value)
1033        if value is None:
1034            return None
1035        return self.to_python(value)
1036
1037
1038class CharField(Field):
1039    def __init__(self, *args, db_collation=None, **kwargs):
1040        super().__init__(*args, **kwargs)
1041        self.db_collation = db_collation
1042        if self.max_length is not None:
1043            self.validators.append(validators.MaxLengthValidator(self.max_length))
1044
1045    @property
1046    def description(self):
1047        if self.max_length is not None:
1048            return "String (up to %(max_length)s)"
1049        else:
1050            return "String (unlimited)"
1051
1052    def check(self, **kwargs):
1053        databases = kwargs.get("databases") or []
1054        return [
1055            *super().check(**kwargs),
1056            *self._check_db_collation(databases),
1057            *self._check_max_length_attribute(**kwargs),
1058        ]
1059
1060    def _check_max_length_attribute(self, **kwargs):
1061        if self.max_length is None:
1062            if (
1063                connection.features.supports_unlimited_charfield
1064                or "supports_unlimited_charfield"
1065                in self.model._meta.required_db_features
1066            ):
1067                return []
1068            return [
1069                preflight.Error(
1070                    "CharFields must define a 'max_length' attribute.",
1071                    obj=self,
1072                    id="fields.E120",
1073                )
1074            ]
1075        elif (
1076            not isinstance(self.max_length, int)
1077            or isinstance(self.max_length, bool)
1078            or self.max_length <= 0
1079        ):
1080            return [
1081                preflight.Error(
1082                    "'max_length' must be a positive integer.",
1083                    obj=self,
1084                    id="fields.E121",
1085                )
1086            ]
1087        else:
1088            return []
1089
1090    def _check_db_collation(self, databases):
1091        errors = []
1092        for db in databases:
1093            if not router.allow_migrate_model(db, self.model):
1094                continue
1095            connection = connections[db]
1096            if not (
1097                self.db_collation is None
1098                or "supports_collation_on_charfield"
1099                in self.model._meta.required_db_features
1100                or connection.features.supports_collation_on_charfield
1101            ):
1102                errors.append(
1103                    preflight.Error(
1104                        "%s does not support a database collation on "
1105                        "CharFields." % connection.display_name,
1106                        obj=self,
1107                        id="fields.E190",
1108                    ),
1109                )
1110        return errors
1111
1112    def cast_db_type(self, connection):
1113        if self.max_length is None:
1114            return connection.ops.cast_char_field_without_max_length
1115        return super().cast_db_type(connection)
1116
1117    def db_parameters(self, connection):
1118        db_params = super().db_parameters(connection)
1119        db_params["collation"] = self.db_collation
1120        return db_params
1121
1122    def get_internal_type(self):
1123        return "CharField"
1124
1125    def to_python(self, value):
1126        if isinstance(value, str) or value is None:
1127            return value
1128        return str(value)
1129
1130    def get_prep_value(self, value):
1131        value = super().get_prep_value(value)
1132        return self.to_python(value)
1133
1134    def deconstruct(self):
1135        name, path, args, kwargs = super().deconstruct()
1136        if self.db_collation:
1137            kwargs["db_collation"] = self.db_collation
1138        return name, path, args, kwargs
1139
1140
1141class CommaSeparatedIntegerField(CharField):
1142    default_validators = [validators.validate_comma_separated_integer_list]
1143    description = "Comma-separated integers"
1144    system_check_removed_details = {
1145        "msg": (
1146            "CommaSeparatedIntegerField is removed except for support in "
1147            "historical migrations."
1148        ),
1149        "hint": (
1150            "Use CharField(validators=[validate_comma_separated_integer_list]) "
1151            "instead."
1152        ),
1153        "id": "fields.E901",
1154    }
1155
1156
1157def _to_naive(value):
1158    if timezone.is_aware(value):
1159        value = timezone.make_naive(value, datetime.timezone.utc)
1160    return value
1161
1162
1163def _get_naive_now():
1164    return _to_naive(timezone.now())
1165
1166
1167class DateTimeCheckMixin:
1168    def check(self, **kwargs):
1169        return [
1170            *super().check(**kwargs),
1171            *self._check_mutually_exclusive_options(),
1172            *self._check_fix_default_value(),
1173        ]
1174
1175    def _check_mutually_exclusive_options(self):
1176        # auto_now, auto_now_add, and default are mutually exclusive
1177        # options. The use of more than one of these options together
1178        # will trigger an Error
1179        mutually_exclusive_options = [
1180            self.auto_now_add,
1181            self.auto_now,
1182            self.has_default(),
1183        ]
1184        enabled_options = [
1185            option not in (None, False) for option in mutually_exclusive_options
1186        ].count(True)
1187        if enabled_options > 1:
1188            return [
1189                preflight.Error(
1190                    "The options auto_now, auto_now_add, and default "
1191                    "are mutually exclusive. Only one of these options "
1192                    "may be present.",
1193                    obj=self,
1194                    id="fields.E160",
1195                )
1196            ]
1197        else:
1198            return []
1199
1200    def _check_fix_default_value(self):
1201        return []
1202
1203    # Concrete subclasses use this in their implementations of
1204    # _check_fix_default_value().
1205    def _check_if_value_fixed(self, value, now=None):
1206        """
1207        Check if the given value appears to have been provided as a "fixed"
1208        time value, and include a warning in the returned list if it does. The
1209        value argument must be a date object or aware/naive datetime object. If
1210        now is provided, it must be a naive datetime object.
1211        """
1212        if now is None:
1213            now = _get_naive_now()
1214        offset = datetime.timedelta(seconds=10)
1215        lower = now - offset
1216        upper = now + offset
1217        if isinstance(value, datetime.datetime):
1218            value = _to_naive(value)
1219        else:
1220            assert isinstance(value, datetime.date)
1221            lower = lower.date()
1222            upper = upper.date()
1223        if lower <= value <= upper:
1224            return [
1225                preflight.Warning(
1226                    "Fixed default value provided.",
1227                    hint=(
1228                        "It seems you set a fixed date / time / datetime "
1229                        "value as default for this field. This may not be "
1230                        "what you want. If you want to have the current date "
1231                        "as default, use `plain.utils.timezone.now`"
1232                    ),
1233                    obj=self,
1234                    id="fields.W161",
1235                )
1236            ]
1237        return []
1238
1239
1240class DateField(DateTimeCheckMixin, Field):
1241    empty_strings_allowed = False
1242    default_error_messages = {
1243        "invalid": "“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD format.",
1244        "invalid_date": "“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid date.",
1245    }
1246    description = "Date (without time)"
1247
1248    def __init__(self, name=None, auto_now=False, auto_now_add=False, **kwargs):
1249        self.auto_now, self.auto_now_add = auto_now, auto_now_add
1250        if auto_now or auto_now_add:
1251            kwargs["editable"] = False
1252            kwargs["blank"] = True
1253        super().__init__(name, **kwargs)
1254
1255    def _check_fix_default_value(self):
1256        """
1257        Warn that using an actual date or datetime value is probably wrong;
1258        it's only evaluated on server startup.
1259        """
1260        if not self.has_default():
1261            return []
1262
1263        value = self.default
1264        if isinstance(value, datetime.datetime):
1265            value = _to_naive(value).date()
1266        elif isinstance(value, datetime.date):
1267            pass
1268        else:
1269            # No explicit date / datetime value -- no checks necessary
1270            return []
1271        # At this point, value is a date object.
1272        return self._check_if_value_fixed(value)
1273
1274    def deconstruct(self):
1275        name, path, args, kwargs = super().deconstruct()
1276        if self.auto_now:
1277            kwargs["auto_now"] = True
1278        if self.auto_now_add:
1279            kwargs["auto_now_add"] = True
1280        if self.auto_now or self.auto_now_add:
1281            del kwargs["editable"]
1282            del kwargs["blank"]
1283        return name, path, args, kwargs
1284
1285    def get_internal_type(self):
1286        return "DateField"
1287
1288    def to_python(self, value):
1289        if value is None:
1290            return value
1291        if isinstance(value, datetime.datetime):
1292            if settings.USE_TZ and timezone.is_aware(value):
1293                # Convert aware datetimes to the default time zone
1294                # before casting them to dates (#17742).
1295                default_timezone = timezone.get_default_timezone()
1296                value = timezone.make_naive(value, default_timezone)
1297            return value.date()
1298        if isinstance(value, datetime.date):
1299            return value
1300
1301        try:
1302            parsed = parse_date(value)
1303            if parsed is not None:
1304                return parsed
1305        except ValueError:
1306            raise exceptions.ValidationError(
1307                self.error_messages["invalid_date"],
1308                code="invalid_date",
1309                params={"value": value},
1310            )
1311
1312        raise exceptions.ValidationError(
1313            self.error_messages["invalid"],
1314            code="invalid",
1315            params={"value": value},
1316        )
1317
1318    def pre_save(self, model_instance, add):
1319        if self.auto_now or (self.auto_now_add and add):
1320            value = datetime.date.today()
1321            setattr(model_instance, self.attname, value)
1322            return value
1323        else:
1324            return super().pre_save(model_instance, add)
1325
1326    def contribute_to_class(self, cls, name, **kwargs):
1327        super().contribute_to_class(cls, name, **kwargs)
1328        if not self.null:
1329            setattr(
1330                cls,
1331                "get_next_by_%s" % self.name,
1332                partialmethod(
1333                    cls._get_next_or_previous_by_FIELD, field=self, is_next=True
1334                ),
1335            )
1336            setattr(
1337                cls,
1338                "get_previous_by_%s" % self.name,
1339                partialmethod(
1340                    cls._get_next_or_previous_by_FIELD, field=self, is_next=False
1341                ),
1342            )
1343
1344    def get_prep_value(self, value):
1345        value = super().get_prep_value(value)
1346        return self.to_python(value)
1347
1348    def get_db_prep_value(self, value, connection, prepared=False):
1349        # Casts dates into the format expected by the backend
1350        if not prepared:
1351            value = self.get_prep_value(value)
1352        return connection.ops.adapt_datefield_value(value)
1353
1354    def value_to_string(self, obj):
1355        val = self.value_from_object(obj)
1356        return "" if val is None else val.isoformat()
1357
1358
1359class DateTimeField(DateField):
1360    empty_strings_allowed = False
1361    default_error_messages = {
1362        "invalid": "“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] format.",
1363        "invalid_date": "“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid date.",
1364        "invalid_datetime": "“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]) but it is an invalid date/time.",
1365    }
1366    description = "Date (with time)"
1367
1368    # __init__ is inherited from DateField
1369
1370    def _check_fix_default_value(self):
1371        """
1372        Warn that using an actual date or datetime value is probably wrong;
1373        it's only evaluated on server startup.
1374        """
1375        if not self.has_default():
1376            return []
1377
1378        value = self.default
1379        if isinstance(value, datetime.datetime | datetime.date):
1380            return self._check_if_value_fixed(value)
1381        # No explicit date / datetime value -- no checks necessary.
1382        return []
1383
1384    def get_internal_type(self):
1385        return "DateTimeField"
1386
1387    def to_python(self, value):
1388        if value is None:
1389            return value
1390        if isinstance(value, datetime.datetime):
1391            return value
1392        if isinstance(value, datetime.date):
1393            value = datetime.datetime(value.year, value.month, value.day)
1394            if settings.USE_TZ:
1395                # For backwards compatibility, interpret naive datetimes in
1396                # local time. This won't work during DST change, but we can't
1397                # do much about it, so we let the exceptions percolate up the
1398                # call stack.
1399                warnings.warn(
1400                    "DateTimeField {}.{} received a naive datetime "
1401                    "({}) while time zone support is active.".format(
1402                        self.model.__name__, self.name, value
1403                    ),
1404                    RuntimeWarning,
1405                )
1406                default_timezone = timezone.get_default_timezone()
1407                value = timezone.make_aware(value, default_timezone)
1408            return value
1409
1410        try:
1411            parsed = parse_datetime(value)
1412            if parsed is not None:
1413                return parsed
1414        except ValueError:
1415            raise exceptions.ValidationError(
1416                self.error_messages["invalid_datetime"],
1417                code="invalid_datetime",
1418                params={"value": value},
1419            )
1420
1421        try:
1422            parsed = parse_date(value)
1423            if parsed is not None:
1424                return datetime.datetime(parsed.year, parsed.month, parsed.day)
1425        except ValueError:
1426            raise exceptions.ValidationError(
1427                self.error_messages["invalid_date"],
1428                code="invalid_date",
1429                params={"value": value},
1430            )
1431
1432        raise exceptions.ValidationError(
1433            self.error_messages["invalid"],
1434            code="invalid",
1435            params={"value": value},
1436        )
1437
1438    def pre_save(self, model_instance, add):
1439        if self.auto_now or (self.auto_now_add and add):
1440            value = timezone.now()
1441            setattr(model_instance, self.attname, value)
1442            return value
1443        else:
1444            return super().pre_save(model_instance, add)
1445
1446    # contribute_to_class is inherited from DateField, it registers
1447    # get_next_by_FOO and get_prev_by_FOO
1448
1449    def get_prep_value(self, value):
1450        value = super().get_prep_value(value)
1451        value = self.to_python(value)
1452        if value is not None and settings.USE_TZ and timezone.is_naive(value):
1453            # For backwards compatibility, interpret naive datetimes in local
1454            # time. This won't work during DST change, but we can't do much
1455            # about it, so we let the exceptions percolate up the call stack.
1456            try:
1457                name = f"{self.model.__name__}.{self.name}"
1458            except AttributeError:
1459                name = "(unbound)"
1460            warnings.warn(
1461                f"DateTimeField {name} received a naive datetime ({value})"
1462                " while time zone support is active.",
1463                RuntimeWarning,
1464            )
1465            default_timezone = timezone.get_default_timezone()
1466            value = timezone.make_aware(value, default_timezone)
1467        return value
1468
1469    def get_db_prep_value(self, value, connection, prepared=False):
1470        # Casts datetimes into the format expected by the backend
1471        if not prepared:
1472            value = self.get_prep_value(value)
1473        return connection.ops.adapt_datetimefield_value(value)
1474
1475    def value_to_string(self, obj):
1476        val = self.value_from_object(obj)
1477        return "" if val is None else val.isoformat()
1478
1479
1480class DecimalField(Field):
1481    empty_strings_allowed = False
1482    default_error_messages = {
1483        "invalid": "“%(value)s” value must be a decimal number.",
1484    }
1485    description = "Decimal number"
1486
1487    def __init__(
1488        self,
1489        name=None,
1490        max_digits=None,
1491        decimal_places=None,
1492        **kwargs,
1493    ):
1494        self.max_digits, self.decimal_places = max_digits, decimal_places
1495        super().__init__(name, **kwargs)
1496
1497    def check(self, **kwargs):
1498        errors = super().check(**kwargs)
1499
1500        digits_errors = [
1501            *self._check_decimal_places(),
1502            *self._check_max_digits(),
1503        ]
1504        if not digits_errors:
1505            errors.extend(self._check_decimal_places_and_max_digits(**kwargs))
1506        else:
1507            errors.extend(digits_errors)
1508        return errors
1509
1510    def _check_decimal_places(self):
1511        try:
1512            decimal_places = int(self.decimal_places)
1513            if decimal_places < 0:
1514                raise ValueError()
1515        except TypeError:
1516            return [
1517                preflight.Error(
1518                    "DecimalFields must define a 'decimal_places' attribute.",
1519                    obj=self,
1520                    id="fields.E130",
1521                )
1522            ]
1523        except ValueError:
1524            return [
1525                preflight.Error(
1526                    "'decimal_places' must be a non-negative integer.",
1527                    obj=self,
1528                    id="fields.E131",
1529                )
1530            ]
1531        else:
1532            return []
1533
1534    def _check_max_digits(self):
1535        try:
1536            max_digits = int(self.max_digits)
1537            if max_digits <= 0:
1538                raise ValueError()
1539        except TypeError:
1540            return [
1541                preflight.Error(
1542                    "DecimalFields must define a 'max_digits' attribute.",
1543                    obj=self,
1544                    id="fields.E132",
1545                )
1546            ]
1547        except ValueError:
1548            return [
1549                preflight.Error(
1550                    "'max_digits' must be a positive integer.",
1551                    obj=self,
1552                    id="fields.E133",
1553                )
1554            ]
1555        else:
1556            return []
1557
1558    def _check_decimal_places_and_max_digits(self, **kwargs):
1559        if int(self.decimal_places) > int(self.max_digits):
1560            return [
1561                preflight.Error(
1562                    "'max_digits' must be greater or equal to 'decimal_places'.",
1563                    obj=self,
1564                    id="fields.E134",
1565                )
1566            ]
1567        return []
1568
1569    @cached_property
1570    def validators(self):
1571        return super().validators + [
1572            validators.DecimalValidator(self.max_digits, self.decimal_places)
1573        ]
1574
1575    @cached_property
1576    def context(self):
1577        return decimal.Context(prec=self.max_digits)
1578
1579    def deconstruct(self):
1580        name, path, args, kwargs = super().deconstruct()
1581        if self.max_digits is not None:
1582            kwargs["max_digits"] = self.max_digits
1583        if self.decimal_places is not None:
1584            kwargs["decimal_places"] = self.decimal_places
1585        return name, path, args, kwargs
1586
1587    def get_internal_type(self):
1588        return "DecimalField"
1589
1590    def to_python(self, value):
1591        if value is None:
1592            return value
1593        try:
1594            if isinstance(value, float):
1595                decimal_value = self.context.create_decimal_from_float(value)
1596            else:
1597                decimal_value = decimal.Decimal(value)
1598        except (decimal.InvalidOperation, TypeError, ValueError):
1599            raise exceptions.ValidationError(
1600                self.error_messages["invalid"],
1601                code="invalid",
1602                params={"value": value},
1603            )
1604        if not decimal_value.is_finite():
1605            raise exceptions.ValidationError(
1606                self.error_messages["invalid"],
1607                code="invalid",
1608                params={"value": value},
1609            )
1610        return decimal_value
1611
1612    def get_db_prep_value(self, value, connection, prepared=False):
1613        if not prepared:
1614            value = self.get_prep_value(value)
1615        if hasattr(value, "as_sql"):
1616            return value
1617        return connection.ops.adapt_decimalfield_value(
1618            value, self.max_digits, self.decimal_places
1619        )
1620
1621    def get_prep_value(self, value):
1622        value = super().get_prep_value(value)
1623        return self.to_python(value)
1624
1625
1626class DurationField(Field):
1627    """
1628    Store timedelta objects.
1629
1630    Use interval on PostgreSQL, INTERVAL DAY TO SECOND on Oracle, and bigint
1631    of microseconds on other databases.
1632    """
1633
1634    empty_strings_allowed = False
1635    default_error_messages = {
1636        "invalid": "“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[.uuuuuu] format.",
1637    }
1638    description = "Duration"
1639
1640    def get_internal_type(self):
1641        return "DurationField"
1642
1643    def to_python(self, value):
1644        if value is None:
1645            return value
1646        if isinstance(value, datetime.timedelta):
1647            return value
1648        try:
1649            parsed = parse_duration(value)
1650        except ValueError:
1651            pass
1652        else:
1653            if parsed is not None:
1654                return parsed
1655
1656        raise exceptions.ValidationError(
1657            self.error_messages["invalid"],
1658            code="invalid",
1659            params={"value": value},
1660        )
1661
1662    def get_db_prep_value(self, value, connection, prepared=False):
1663        if connection.features.has_native_duration_field:
1664            return value
1665        if value is None:
1666            return None
1667        return duration_microseconds(value)
1668
1669    def get_db_converters(self, connection):
1670        converters = []
1671        if not connection.features.has_native_duration_field:
1672            converters.append(connection.ops.convert_durationfield_value)
1673        return converters + super().get_db_converters(connection)
1674
1675    def value_to_string(self, obj):
1676        val = self.value_from_object(obj)
1677        return "" if val is None else duration_string(val)
1678
1679
1680class EmailField(CharField):
1681    default_validators = [validators.validate_email]
1682    description = "Email address"
1683
1684    def __init__(self, *args, **kwargs):
1685        # max_length=254 to be compliant with RFCs 3696 and 5321
1686        kwargs.setdefault("max_length", 254)
1687        super().__init__(*args, **kwargs)
1688
1689    def deconstruct(self):
1690        name, path, args, kwargs = super().deconstruct()
1691        # We do not exclude max_length if it matches default as we want to change
1692        # the default in future.
1693        return name, path, args, kwargs
1694
1695
1696class FloatField(Field):
1697    empty_strings_allowed = False
1698    default_error_messages = {
1699        "invalid": "“%(value)s” value must be a float.",
1700    }
1701    description = "Floating point number"
1702
1703    def get_prep_value(self, value):
1704        value = super().get_prep_value(value)
1705        if value is None:
1706            return None
1707        try:
1708            return float(value)
1709        except (TypeError, ValueError) as e:
1710            raise e.__class__(
1711                f"Field '{self.name}' expected a number but got {value!r}.",
1712            ) from e
1713
1714    def get_internal_type(self):
1715        return "FloatField"
1716
1717    def to_python(self, value):
1718        if value is None:
1719            return value
1720        try:
1721            return float(value)
1722        except (TypeError, ValueError):
1723            raise exceptions.ValidationError(
1724                self.error_messages["invalid"],
1725                code="invalid",
1726                params={"value": value},
1727            )
1728
1729
1730class IntegerField(Field):
1731    empty_strings_allowed = False
1732    default_error_messages = {
1733        "invalid": "“%(value)s” value must be an integer.",
1734    }
1735    description = "Integer"
1736
1737    def check(self, **kwargs):
1738        return [
1739            *super().check(**kwargs),
1740            *self._check_max_length_warning(),
1741        ]
1742
1743    def _check_max_length_warning(self):
1744        if self.max_length is not None:
1745            return [
1746                preflight.Warning(
1747                    "'max_length' is ignored when used with %s."
1748                    % self.__class__.__name__,
1749                    hint="Remove 'max_length' from field",
1750                    obj=self,
1751                    id="fields.W122",
1752                )
1753            ]
1754        return []
1755
1756    @cached_property
1757    def validators(self):
1758        # These validators can't be added at field initialization time since
1759        # they're based on values retrieved from `connection`.
1760        validators_ = super().validators
1761        internal_type = self.get_internal_type()
1762        min_value, max_value = connection.ops.integer_field_range(internal_type)
1763        if min_value is not None and not any(
1764            (
1765                isinstance(validator, validators.MinValueValidator)
1766                and (
1767                    validator.limit_value()
1768                    if callable(validator.limit_value)
1769                    else validator.limit_value
1770                )
1771                >= min_value
1772            )
1773            for validator in validators_
1774        ):
1775            validators_.append(validators.MinValueValidator(min_value))
1776        if max_value is not None and not any(
1777            (
1778                isinstance(validator, validators.MaxValueValidator)
1779                and (
1780                    validator.limit_value()
1781                    if callable(validator.limit_value)
1782                    else validator.limit_value
1783                )
1784                <= max_value
1785            )
1786            for validator in validators_
1787        ):
1788            validators_.append(validators.MaxValueValidator(max_value))
1789        return validators_
1790
1791    def get_prep_value(self, value):
1792        value = super().get_prep_value(value)
1793        if value is None:
1794            return None
1795        try:
1796            return int(value)
1797        except (TypeError, ValueError) as e:
1798            raise e.__class__(
1799                f"Field '{self.name}' expected a number but got {value!r}.",
1800            ) from e
1801
1802    def get_db_prep_value(self, value, connection, prepared=False):
1803        value = super().get_db_prep_value(value, connection, prepared)
1804        return connection.ops.adapt_integerfield_value(value, self.get_internal_type())
1805
1806    def get_internal_type(self):
1807        return "IntegerField"
1808
1809    def to_python(self, value):
1810        if value is None:
1811            return value
1812        try:
1813            return int(value)
1814        except (TypeError, ValueError):
1815            raise exceptions.ValidationError(
1816                self.error_messages["invalid"],
1817                code="invalid",
1818                params={"value": value},
1819            )
1820
1821
1822class BigIntegerField(IntegerField):
1823    description = "Big (8 byte) integer"
1824    MAX_BIGINT = 9223372036854775807
1825
1826    def get_internal_type(self):
1827        return "BigIntegerField"
1828
1829
1830class SmallIntegerField(IntegerField):
1831    description = "Small integer"
1832
1833    def get_internal_type(self):
1834        return "SmallIntegerField"
1835
1836
1837class IPAddressField(Field):
1838    empty_strings_allowed = False
1839    description = "IPv4 address"
1840    system_check_removed_details = {
1841        "msg": (
1842            "IPAddressField has been removed except for support in "
1843            "historical migrations."
1844        ),
1845        "hint": "Use GenericIPAddressField instead.",
1846        "id": "fields.E900",
1847    }
1848
1849    def __init__(self, *args, **kwargs):
1850        kwargs["max_length"] = 15
1851        super().__init__(*args, **kwargs)
1852
1853    def deconstruct(self):
1854        name, path, args, kwargs = super().deconstruct()
1855        del kwargs["max_length"]
1856        return name, path, args, kwargs
1857
1858    def get_prep_value(self, value):
1859        value = super().get_prep_value(value)
1860        if value is None:
1861            return None
1862        return str(value)
1863
1864    def get_internal_type(self):
1865        return "IPAddressField"
1866
1867
1868class GenericIPAddressField(Field):
1869    empty_strings_allowed = False
1870    description = "IP address"
1871    default_error_messages = {}
1872
1873    def __init__(
1874        self,
1875        name=None,
1876        protocol="both",
1877        unpack_ipv4=False,
1878        *args,
1879        **kwargs,
1880    ):
1881        self.unpack_ipv4 = unpack_ipv4
1882        self.protocol = protocol
1883        (
1884            self.default_validators,
1885            invalid_error_message,
1886        ) = validators.ip_address_validators(protocol, unpack_ipv4)
1887        self.default_error_messages["invalid"] = invalid_error_message
1888        kwargs["max_length"] = 39
1889        super().__init__(name, *args, **kwargs)
1890
1891    def check(self, **kwargs):
1892        return [
1893            *super().check(**kwargs),
1894            *self._check_blank_and_null_values(**kwargs),
1895        ]
1896
1897    def _check_blank_and_null_values(self, **kwargs):
1898        if not getattr(self, "null", False) and getattr(self, "blank", False):
1899            return [
1900                preflight.Error(
1901                    "GenericIPAddressFields cannot have blank=True if null=False, "
1902                    "as blank values are stored as nulls.",
1903                    obj=self,
1904                    id="fields.E150",
1905                )
1906            ]
1907        return []
1908
1909    def deconstruct(self):
1910        name, path, args, kwargs = super().deconstruct()
1911        if self.unpack_ipv4 is not False:
1912            kwargs["unpack_ipv4"] = self.unpack_ipv4
1913        if self.protocol != "both":
1914            kwargs["protocol"] = self.protocol
1915        if kwargs.get("max_length") == 39:
1916            del kwargs["max_length"]
1917        return name, path, args, kwargs
1918
1919    def get_internal_type(self):
1920        return "GenericIPAddressField"
1921
1922    def to_python(self, value):
1923        if value is None:
1924            return None
1925        if not isinstance(value, str):
1926            value = str(value)
1927        value = value.strip()
1928        if ":" in value:
1929            return clean_ipv6_address(
1930                value, self.unpack_ipv4, self.error_messages["invalid"]
1931            )
1932        return value
1933
1934    def get_db_prep_value(self, value, connection, prepared=False):
1935        if not prepared:
1936            value = self.get_prep_value(value)
1937        return connection.ops.adapt_ipaddressfield_value(value)
1938
1939    def get_prep_value(self, value):
1940        value = super().get_prep_value(value)
1941        if value is None:
1942            return None
1943        if value and ":" in value:
1944            try:
1945                return clean_ipv6_address(value, self.unpack_ipv4)
1946            except exceptions.ValidationError:
1947                pass
1948        return str(value)
1949
1950
1951class NullBooleanField(BooleanField):
1952    default_error_messages = {
1953        "invalid": "“%(value)s” value must be either None, True or False.",
1954        "invalid_nullable": "“%(value)s” value must be either None, True or False.",
1955    }
1956    description = "Boolean (Either True, False or None)"
1957    system_check_removed_details = {
1958        "msg": (
1959            "NullBooleanField is removed except for support in historical "
1960            "migrations."
1961        ),
1962        "hint": "Use BooleanField(null=True) instead.",
1963        "id": "fields.E903",
1964    }
1965
1966    def __init__(self, *args, **kwargs):
1967        kwargs["null"] = True
1968        kwargs["blank"] = True
1969        super().__init__(*args, **kwargs)
1970
1971    def deconstruct(self):
1972        name, path, args, kwargs = super().deconstruct()
1973        del kwargs["null"]
1974        del kwargs["blank"]
1975        return name, path, args, kwargs
1976
1977
1978class PositiveIntegerRelDbTypeMixin:
1979    def __init_subclass__(cls, **kwargs):
1980        super().__init_subclass__(**kwargs)
1981        if not hasattr(cls, "integer_field_class"):
1982            cls.integer_field_class = next(
1983                (
1984                    parent
1985                    for parent in cls.__mro__[1:]
1986                    if issubclass(parent, IntegerField)
1987                ),
1988                None,
1989            )
1990
1991    def rel_db_type(self, connection):
1992        """
1993        Return the data type that a related field pointing to this field should
1994        use. In most cases, a foreign key pointing to a positive integer
1995        primary key will have an integer column data type but some databases
1996        (e.g. MySQL) have an unsigned integer type. In that case
1997        (related_fields_match_type=True), the primary key should return its
1998        db_type.
1999        """
2000        if connection.features.related_fields_match_type:
2001            return self.db_type(connection)
2002        else:
2003            return self.integer_field_class().db_type(connection=connection)
2004
2005
2006class PositiveBigIntegerField(PositiveIntegerRelDbTypeMixin, BigIntegerField):
2007    description = "Positive big integer"
2008
2009    def get_internal_type(self):
2010        return "PositiveBigIntegerField"
2011
2012
2013class PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField):
2014    description = "Positive integer"
2015
2016    def get_internal_type(self):
2017        return "PositiveIntegerField"
2018
2019
2020class PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, SmallIntegerField):
2021    description = "Positive small integer"
2022
2023    def get_internal_type(self):
2024        return "PositiveSmallIntegerField"
2025
2026
2027class SlugField(CharField):
2028    default_validators = [validators.validate_slug]
2029    description = "Slug (up to %(max_length)s)"
2030
2031    def __init__(
2032        self, *args, max_length=50, db_index=True, allow_unicode=False, **kwargs
2033    ):
2034        self.allow_unicode = allow_unicode
2035        if self.allow_unicode:
2036            self.default_validators = [validators.validate_unicode_slug]
2037        super().__init__(*args, max_length=max_length, db_index=db_index, **kwargs)
2038
2039    def deconstruct(self):
2040        name, path, args, kwargs = super().deconstruct()
2041        if kwargs.get("max_length") == 50:
2042            del kwargs["max_length"]
2043        if self.db_index is False:
2044            kwargs["db_index"] = False
2045        else:
2046            del kwargs["db_index"]
2047        if self.allow_unicode is not False:
2048            kwargs["allow_unicode"] = self.allow_unicode
2049        return name, path, args, kwargs
2050
2051    def get_internal_type(self):
2052        return "SlugField"
2053
2054
2055class TextField(Field):
2056    description = "Text"
2057
2058    def __init__(self, *args, db_collation=None, **kwargs):
2059        super().__init__(*args, **kwargs)
2060        self.db_collation = db_collation
2061
2062    def check(self, **kwargs):
2063        databases = kwargs.get("databases") or []
2064        return [
2065            *super().check(**kwargs),
2066            *self._check_db_collation(databases),
2067        ]
2068
2069    def _check_db_collation(self, databases):
2070        errors = []
2071        for db in databases:
2072            if not router.allow_migrate_model(db, self.model):
2073                continue
2074            connection = connections[db]
2075            if not (
2076                self.db_collation is None
2077                or "supports_collation_on_textfield"
2078                in self.model._meta.required_db_features
2079                or connection.features.supports_collation_on_textfield
2080            ):
2081                errors.append(
2082                    preflight.Error(
2083                        "%s does not support a database collation on "
2084                        "TextFields." % connection.display_name,
2085                        obj=self,
2086                        id="fields.E190",
2087                    ),
2088                )
2089        return errors
2090
2091    def db_parameters(self, connection):
2092        db_params = super().db_parameters(connection)
2093        db_params["collation"] = self.db_collation
2094        return db_params
2095
2096    def get_internal_type(self):
2097        return "TextField"
2098
2099    def to_python(self, value):
2100        if isinstance(value, str) or value is None:
2101            return value
2102        return str(value)
2103
2104    def get_prep_value(self, value):
2105        value = super().get_prep_value(value)
2106        return self.to_python(value)
2107
2108    def deconstruct(self):
2109        name, path, args, kwargs = super().deconstruct()
2110        if self.db_collation:
2111            kwargs["db_collation"] = self.db_collation
2112        return name, path, args, kwargs
2113
2114
2115class TimeField(DateTimeCheckMixin, Field):
2116    empty_strings_allowed = False
2117    default_error_messages = {
2118        "invalid": "“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] format.",
2119        "invalid_time": "“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an invalid time.",
2120    }
2121    description = "Time"
2122
2123    def __init__(self, name=None, auto_now=False, auto_now_add=False, **kwargs):
2124        self.auto_now, self.auto_now_add = auto_now, auto_now_add
2125        if auto_now or auto_now_add:
2126            kwargs["editable"] = False
2127            kwargs["blank"] = True
2128        super().__init__(name, **kwargs)
2129
2130    def _check_fix_default_value(self):
2131        """
2132        Warn that using an actual date or datetime value is probably wrong;
2133        it's only evaluated on server startup.
2134        """
2135        if not self.has_default():
2136            return []
2137
2138        value = self.default
2139        if isinstance(value, datetime.datetime):
2140            now = None
2141        elif isinstance(value, datetime.time):
2142            now = _get_naive_now()
2143            # This will not use the right date in the race condition where now
2144            # is just before the date change and value is just past 0:00.
2145            value = datetime.datetime.combine(now.date(), value)
2146        else:
2147            # No explicit time / datetime value -- no checks necessary
2148            return []
2149        # At this point, value is a datetime object.
2150        return self._check_if_value_fixed(value, now=now)
2151
2152    def deconstruct(self):
2153        name, path, args, kwargs = super().deconstruct()
2154        if self.auto_now is not False:
2155            kwargs["auto_now"] = self.auto_now
2156        if self.auto_now_add is not False:
2157            kwargs["auto_now_add"] = self.auto_now_add
2158        if self.auto_now or self.auto_now_add:
2159            del kwargs["blank"]
2160            del kwargs["editable"]
2161        return name, path, args, kwargs
2162
2163    def get_internal_type(self):
2164        return "TimeField"
2165
2166    def to_python(self, value):
2167        if value is None:
2168            return None
2169        if isinstance(value, datetime.time):
2170            return value
2171        if isinstance(value, datetime.datetime):
2172            # Not usually a good idea to pass in a datetime here (it loses
2173            # information), but this can be a side-effect of interacting with a
2174            # database backend (e.g. Oracle), so we'll be accommodating.
2175            return value.time()
2176
2177        try:
2178            parsed = parse_time(value)
2179            if parsed is not None:
2180                return parsed
2181        except ValueError:
2182            raise exceptions.ValidationError(
2183                self.error_messages["invalid_time"],
2184                code="invalid_time",
2185                params={"value": value},
2186            )
2187
2188        raise exceptions.ValidationError(
2189            self.error_messages["invalid"],
2190            code="invalid",
2191            params={"value": value},
2192        )
2193
2194    def pre_save(self, model_instance, add):
2195        if self.auto_now or (self.auto_now_add and add):
2196            value = datetime.datetime.now().time()
2197            setattr(model_instance, self.attname, value)
2198            return value
2199        else:
2200            return super().pre_save(model_instance, add)
2201
2202    def get_prep_value(self, value):
2203        value = super().get_prep_value(value)
2204        return self.to_python(value)
2205
2206    def get_db_prep_value(self, value, connection, prepared=False):
2207        # Casts times into the format expected by the backend
2208        if not prepared:
2209            value = self.get_prep_value(value)
2210        return connection.ops.adapt_timefield_value(value)
2211
2212    def value_to_string(self, obj):
2213        val = self.value_from_object(obj)
2214        return "" if val is None else val.isoformat()
2215
2216
2217class URLField(CharField):
2218    default_validators = [validators.URLValidator()]
2219    description = "URL"
2220
2221    def __init__(self, name=None, **kwargs):
2222        kwargs.setdefault("max_length", 200)
2223        super().__init__(name, **kwargs)
2224
2225    def deconstruct(self):
2226        name, path, args, kwargs = super().deconstruct()
2227        if kwargs.get("max_length") == 200:
2228            del kwargs["max_length"]
2229        return name, path, args, kwargs
2230
2231
2232class BinaryField(Field):
2233    description = "Raw binary data"
2234    empty_values = [None, b""]
2235
2236    def __init__(self, *args, **kwargs):
2237        kwargs.setdefault("editable", False)
2238        super().__init__(*args, **kwargs)
2239        if self.max_length is not None:
2240            self.validators.append(validators.MaxLengthValidator(self.max_length))
2241
2242    def check(self, **kwargs):
2243        return [*super().check(**kwargs), *self._check_str_default_value()]
2244
2245    def _check_str_default_value(self):
2246        if self.has_default() and isinstance(self.default, str):
2247            return [
2248                preflight.Error(
2249                    "BinaryField's default cannot be a string. Use bytes "
2250                    "content instead.",
2251                    obj=self,
2252                    id="fields.E170",
2253                )
2254            ]
2255        return []
2256
2257    def deconstruct(self):
2258        name, path, args, kwargs = super().deconstruct()
2259        if self.editable:
2260            kwargs["editable"] = True
2261        else:
2262            del kwargs["editable"]
2263        return name, path, args, kwargs
2264
2265    def get_internal_type(self):
2266        return "BinaryField"
2267
2268    def get_placeholder(self, value, compiler, connection):
2269        return connection.ops.binary_placeholder_sql(value)
2270
2271    def get_default(self):
2272        if self.has_default() and not callable(self.default):
2273            return self.default
2274        default = super().get_default()
2275        if default == "":
2276            return b""
2277        return default
2278
2279    def get_db_prep_value(self, value, connection, prepared=False):
2280        value = super().get_db_prep_value(value, connection, prepared)
2281        if value is not None:
2282            return connection.Database.Binary(value)
2283        return value
2284
2285    def value_to_string(self, obj):
2286        """Binary data is serialized as base64"""
2287        return b64encode(self.value_from_object(obj)).decode("ascii")
2288
2289    def to_python(self, value):
2290        # If it's a string, it should be base64-encoded data
2291        if isinstance(value, str):
2292            return memoryview(b64decode(value.encode("ascii")))
2293        return value
2294
2295
2296class UUIDField(Field):
2297    default_error_messages = {
2298        "invalid": "“%(value)s” is not a valid UUID.",
2299    }
2300    description = "Universally unique identifier"
2301    empty_strings_allowed = False
2302
2303    def __init__(self, **kwargs):
2304        kwargs["max_length"] = 32
2305        super().__init__(**kwargs)
2306
2307    def deconstruct(self):
2308        name, path, args, kwargs = super().deconstruct()
2309        del kwargs["max_length"]
2310        return name, path, args, kwargs
2311
2312    def get_internal_type(self):
2313        return "UUIDField"
2314
2315    def get_prep_value(self, value):
2316        value = super().get_prep_value(value)
2317        return self.to_python(value)
2318
2319    def get_db_prep_value(self, value, connection, prepared=False):
2320        if value is None:
2321            return None
2322        if not isinstance(value, uuid.UUID):
2323            value = self.to_python(value)
2324
2325        if connection.features.has_native_uuid_field:
2326            return value
2327        return value.hex
2328
2329    def to_python(self, value):
2330        if value is not None and not isinstance(value, uuid.UUID):
2331            input_form = "int" if isinstance(value, int) else "hex"
2332            try:
2333                return uuid.UUID(**{input_form: value})
2334            except (AttributeError, ValueError):
2335                raise exceptions.ValidationError(
2336                    self.error_messages["invalid"],
2337                    code="invalid",
2338                    params={"value": value},
2339                )
2340        return value
2341
2342
2343class AutoFieldMixin:
2344    db_returning = True
2345
2346    def __init__(self, *args, **kwargs):
2347        kwargs["blank"] = True
2348        super().__init__(*args, **kwargs)
2349
2350    def check(self, **kwargs):
2351        return [
2352            *super().check(**kwargs),
2353            *self._check_primary_key(),
2354        ]
2355
2356    def _check_primary_key(self):
2357        if not self.primary_key:
2358            return [
2359                preflight.Error(
2360                    "AutoFields must set primary_key=True.",
2361                    obj=self,
2362                    id="fields.E100",
2363                ),
2364            ]
2365        else:
2366            return []
2367
2368    def deconstruct(self):
2369        name, path, args, kwargs = super().deconstruct()
2370        del kwargs["blank"]
2371        kwargs["primary_key"] = True
2372        return name, path, args, kwargs
2373
2374    def validate(self, value, model_instance):
2375        pass
2376
2377    def get_db_prep_value(self, value, connection, prepared=False):
2378        if not prepared:
2379            value = self.get_prep_value(value)
2380            value = connection.ops.validate_autopk_value(value)
2381        return value
2382
2383    def contribute_to_class(self, cls, name, **kwargs):
2384        if cls._meta.auto_field:
2385            raise ValueError(
2386                "Model %s can't have more than one auto-generated field."
2387                % cls._meta.label
2388            )
2389        super().contribute_to_class(cls, name, **kwargs)
2390        cls._meta.auto_field = self
2391
2392
2393class AutoFieldMeta(type):
2394    """
2395    Metaclass to maintain backward inheritance compatibility for AutoField.
2396
2397    It is intended that AutoFieldMixin become public API when it is possible to
2398    create a non-integer automatically-generated field using column defaults
2399    stored in the database.
2400
2401    In many areas Plain also relies on using isinstance() to check for an
2402    automatically-generated field as a subclass of AutoField. A new flag needs
2403    to be implemented on Field to be used instead.
2404
2405    When these issues have been addressed, this metaclass could be used to
2406    deprecate inheritance from AutoField and use of isinstance() with AutoField
2407    for detecting automatically-generated fields.
2408    """
2409
2410    @property
2411    def _subclasses(self):
2412        return (BigAutoField, SmallAutoField)
2413
2414    def __instancecheck__(self, instance):
2415        return isinstance(instance, self._subclasses) or super().__instancecheck__(
2416            instance
2417        )
2418
2419    def __subclasscheck__(self, subclass):
2420        return issubclass(subclass, self._subclasses) or super().__subclasscheck__(
2421            subclass
2422        )
2423
2424
2425class AutoField(AutoFieldMixin, IntegerField, metaclass=AutoFieldMeta):
2426    def get_internal_type(self):
2427        return "AutoField"
2428
2429    def rel_db_type(self, connection):
2430        return IntegerField().db_type(connection=connection)
2431
2432
2433class BigAutoField(AutoFieldMixin, BigIntegerField):
2434    def get_internal_type(self):
2435        return "BigAutoField"
2436
2437    def rel_db_type(self, connection):
2438        return BigIntegerField().db_type(connection=connection)
2439
2440
2441class SmallAutoField(AutoFieldMixin, SmallIntegerField):
2442    def get_internal_type(self):
2443        return "SmallAutoField"
2444
2445    def rel_db_type(self, connection):
2446        return SmallIntegerField().db_type(connection=connection)