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