Plain is headed towards 1.0! Subscribe for development updates →

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