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