0
# Contrib Packages
1
2
Django's contributed applications provide extended functionality including geographic information systems (GIS), PostgreSQL-specific features, static file handling, sessions, messaging, and multi-site support.
3
4
## Capabilities
5
6
### Geographic Information System (GeoDjango)
7
8
Comprehensive GIS support for geographic and spatial data processing.
9
10
```python { .api }
11
# GIS Model Fields
12
class GeometryField(models.Field):
13
"""
14
Base geometry field for spatial data.
15
16
Stores geometric objects with spatial database support.
17
"""
18
def __init__(self, verbose_name: str = None, srid: int = 4326, spatial_index: bool = True,
19
dim: int = 2, geography: bool = False, extent: tuple = None, tolerance: float = 0.05, **kwargs): ...
20
21
class PointField(GeometryField):
22
"""
23
Field for storing point geometries (longitude, latitude).
24
25
Represents single geographic points with coordinate data.
26
"""
27
28
class LineStringField(GeometryField):
29
"""
30
Field for storing line string geometries.
31
32
Represents connected series of points forming lines or paths.
33
"""
34
35
class PolygonField(GeometryField):
36
"""
37
Field for storing polygon geometries.
38
39
Represents closed geometric shapes with area boundaries.
40
"""
41
42
class MultiPointField(GeometryField):
43
"""
44
Field for storing collections of points.
45
46
Represents multiple discrete geographic points.
47
"""
48
49
class MultiLineStringField(GeometryField):
50
"""
51
Field for storing collections of line strings.
52
53
Represents multiple line segments or polylines.
54
"""
55
56
class MultiPolygonField(GeometryField):
57
"""
58
Field for storing collections of polygons.
59
60
Represents complex areas with multiple polygon boundaries.
61
"""
62
63
class GeometryCollectionField(GeometryField):
64
"""
65
Field for storing mixed geometry collections.
66
67
Represents heterogeneous collections of various geometry types.
68
"""
69
70
# GIS Database Functions
71
class Distance(models.Expression):
72
"""
73
Database function for calculating distance between geometries.
74
"""
75
def __init__(self, expr1, expr2, spheroid: bool = None, **extra): ...
76
77
class Area(models.Expression):
78
"""
79
Database function for calculating geometry area.
80
"""
81
82
class Centroid(models.Expression):
83
"""
84
Database function for finding geometry centroid.
85
"""
86
87
class Length(models.Expression):
88
"""
89
Database function for calculating geometry length.
90
"""
91
92
class Perimeter(models.Expression):
93
"""
94
Database function for calculating polygon perimeter.
95
"""
96
97
class Transform(models.Expression):
98
"""
99
Database function for transforming geometry coordinates.
100
"""
101
def __init__(self, expression, srid: int, **extra): ...
102
103
# GIS Lookup Types
104
class DWithin(models.Lookup):
105
"""
106
Lookup for geometries within specified distance.
107
"""
108
109
class Intersects(models.Lookup):
110
"""
111
Lookup for geometries that intersect.
112
"""
113
114
class Contains(models.Lookup):
115
"""
116
Lookup for geometries that contain another geometry.
117
"""
118
119
class Overlaps(models.Lookup):
120
"""
121
Lookup for geometries that overlap.
122
"""
123
124
class Touches(models.Lookup):
125
"""
126
Lookup for geometries that touch boundaries.
127
"""
128
129
class Within(models.Lookup):
130
"""
131
Lookup for geometries within another geometry.
132
"""
133
134
class Crosses(models.Lookup):
135
"""
136
Lookup for geometries that cross.
137
"""
138
```
139
140
### PostgreSQL-Specific Features
141
142
Enhanced functionality for PostgreSQL database features.
143
144
```python { .api }
145
# PostgreSQL Fields
146
class ArrayField(models.Field):
147
"""
148
Field for storing PostgreSQL arrays.
149
150
Stores ordered collections of values with indexing support.
151
"""
152
def __init__(self, base_field: models.Field, size: int = None, default: list = list, **kwargs): ...
153
154
class HStoreField(models.Field):
155
"""
156
Field for storing PostgreSQL hstore key-value data.
157
158
Stores flexible key-value pairs with indexing and querying.
159
"""
160
def __init__(self, **kwargs): ...
161
162
class JSONField(models.Field):
163
"""
164
Field for storing JSON data in PostgreSQL.
165
166
Stores structured JSON data with native database support.
167
"""
168
def __init__(self, encoder=None, decoder=None, **kwargs): ...
169
170
class CICharField(models.CharField):
171
"""
172
Case-insensitive character field for PostgreSQL.
173
174
Uses citext extension for case-insensitive text storage.
175
"""
176
177
class CIEmailField(models.EmailField):
178
"""
179
Case-insensitive email field for PostgreSQL.
180
"""
181
182
class CITextField(models.TextField):
183
"""
184
Case-insensitive text field for PostgreSQL.
185
"""
186
187
# Range Fields
188
class IntegerRangeField(models.Field):
189
"""
190
Field for storing integer ranges.
191
192
Stores continuous or discrete integer ranges with bounds.
193
"""
194
195
class BigIntegerRangeField(models.Field):
196
"""
197
Field for storing big integer ranges.
198
"""
199
200
class DecimalRangeField(models.Field):
201
"""
202
Field for storing decimal number ranges.
203
"""
204
205
class DateTimeRangeField(models.Field):
206
"""
207
Field for storing datetime ranges.
208
"""
209
210
class DateRangeField(models.Field):
211
"""
212
Field for storing date ranges.
213
"""
214
215
# Full-text Search Fields
216
class SearchVectorField(models.Field):
217
"""
218
Field for storing PostgreSQL full-text search vectors.
219
220
Optimizes text search with pre-computed search vectors.
221
"""
222
223
class SearchQueryField(models.Field):
224
"""
225
Field for storing search queries.
226
"""
227
228
class SearchRankField(models.Field):
229
"""
230
Field for storing search result rankings.
231
"""
232
233
# PostgreSQL Aggregates
234
class ArrayAgg(models.Aggregate):
235
"""
236
Aggregate function for creating arrays from grouped values.
237
"""
238
def __init__(self, expression, distinct: bool = False, filter=None, default=None, ordering=(), **extra): ...
239
240
class BoolAnd(models.Aggregate):
241
"""
242
Aggregate function for boolean AND operations.
243
"""
244
245
class BoolOr(models.Aggregate):
246
"""
247
Aggregate function for boolean OR operations.
248
"""
249
250
class JSONBAgg(models.Aggregate):
251
"""
252
Aggregate function for creating JSONB arrays.
253
"""
254
255
class StringAgg(models.Aggregate):
256
"""
257
Aggregate function for concatenating strings.
258
"""
259
def __init__(self, expression, delimiter: str, distinct: bool = False, filter=None, default=None, ordering=(), **extra): ...
260
261
# PostgreSQL Indexes
262
class BrinIndex(models.Index):
263
"""
264
Block Range Index for large tables.
265
"""
266
def __init__(self, *, fields: list, name: str, autosummarize: bool = None, pages_per_range: int = None, **kwargs): ...
267
268
class BTreeIndex(models.Index):
269
"""
270
B-tree index (default PostgreSQL index).
271
"""
272
273
class GinIndex(models.Index):
274
"""
275
Generalized Inverted Index for composite values.
276
"""
277
def __init__(self, *, fields: list, name: str, fastupdate: bool = None, gin_pending_list_limit: int = None, **kwargs): ...
278
279
class GistIndex(models.Index):
280
"""
281
Generalized Search Tree index for spatial data.
282
"""
283
def __init__(self, *, fields: list, name: str, buffering: bool = None, fillfactor: int = None, **kwargs): ...
284
285
class HashIndex(models.Index):
286
"""
287
Hash index for equality comparisons.
288
"""
289
290
class SpGistIndex(models.Index):
291
"""
292
Space-partitioned Generalized Search Tree index.
293
"""
294
def __init__(self, *, fields: list, name: str, fillfactor: int = None, **kwargs): ...
295
296
# PostgreSQL Constraints
297
class ExclusionConstraint(models.BaseConstraint):
298
"""
299
Exclusion constraint for PostgreSQL.
300
301
Ensures no two rows satisfy specified condition simultaneously.
302
"""
303
def __init__(self, *, name: str, expressions: list, index_type: str = None, condition=None,
304
deferrable: bool = None, include: list = None, opclasses: list = None): ...
305
306
# PostgreSQL Operations
307
class HStoreExtension(migrations.Operation):
308
"""
309
Migration operation for enabling hstore extension.
310
"""
311
312
class CITextExtension(migrations.Operation):
313
"""
314
Migration operation for enabling citext extension.
315
"""
316
317
class TrigramExtension(migrations.Operation):
318
"""
319
Migration operation for enabling pg_trgm extension.
320
"""
321
322
class UnaccentExtension(migrations.Operation):
323
"""
324
Migration operation for enabling unaccent extension.
325
"""
326
```
327
328
### Sessions Framework
329
330
Session management with multiple storage backends.
331
332
```python { .api }
333
class SessionBase:
334
"""
335
Base session interface for all session backends.
336
337
Provides common session functionality across different storage methods.
338
"""
339
TEST_COOKIE_NAME: str = 'testcookie'
340
TEST_COOKIE_VALUE: str = 'worked'
341
342
def __init__(self, session_key: str = None): ...
343
def __contains__(self, key: str) -> bool: ...
344
def __getitem__(self, key: str): ...
345
def __setitem__(self, key: str, value) -> None: ...
346
def __delitem__(self, key: str) -> None: ...
347
def keys(self): ...
348
def items(self): ...
349
def values(self): ...
350
def get(self, key: str, default=None): ...
351
def pop(self, key: str, default=None): ...
352
def setdefault(self, key: str, value): ...
353
def set_test_cookie(self) -> None: ...
354
def test_cookie_worked(self) -> bool: ...
355
def delete_test_cookie(self) -> None: ...
356
def flush(self) -> None: ...
357
def delete(self, session_key: str = None) -> None: ...
358
def cycle_key(self) -> None: ...
359
def is_empty(self) -> bool: ...
360
def get_session_cookie_age(self) -> int: ...
361
def get_expiry_age(self, **kwargs) -> int: ...
362
def get_expiry_date(self, **kwargs): ...
363
def set_expiry(self, value) -> None: ...
364
def get_expire_at_browser_close(self) -> bool: ...
365
def clear_expired(cls) -> None: ...
366
def save(self, must_create: bool = False) -> None: ...
367
def exists(self, session_key: str) -> bool: ...
368
def create(self) -> None: ...
369
def load(self) -> dict: ...
370
371
session_key: str
372
accessed: bool
373
modified: bool
374
375
class SessionStore(SessionBase):
376
"""
377
Database-backed session storage.
378
379
Stores session data in database Session model.
380
"""
381
382
class CachedSessionStore(SessionStore):
383
"""
384
Session storage using cache with database fallback.
385
386
Combines cache performance with database persistence.
387
"""
388
cache_key_prefix: str = 'django.contrib.sessions.cached_db'
389
390
class CacheSessionStore(SessionBase):
391
"""
392
Cache-only session storage.
393
394
Stores session data entirely in cache system.
395
"""
396
cache_key_prefix: str = 'django.contrib.sessions.cache'
397
398
class FileSessionStore(SessionBase):
399
"""
400
File-based session storage.
401
402
Stores session data in individual files on filesystem.
403
"""
404
def __init__(self, session_key: str = None): ...
405
def file_path(self, session_key: str = None) -> str: ...
406
407
class CookieSessionStore(SessionBase):
408
"""
409
Client-side session storage using signed cookies.
410
411
Stores session data in browser cookies with cryptographic signing.
412
"""
413
414
# Session Model
415
class Session(models.Model):
416
"""
417
Database model for session storage.
418
419
Stores session data with expiration and key management.
420
"""
421
session_key: models.CharField
422
session_data: models.TextField
423
expire_date: models.DateTimeField
424
425
objects: SessionManager
426
427
@classmethod
428
def get_session_store_class(cls): ...
429
def get_decoded(self) -> dict: ...
430
431
def get_session_store(import_path: str = None) -> SessionBase:
432
"""
433
Get session store instance by import path.
434
435
Args:
436
import_path: Dotted path to session store class
437
438
Returns:
439
Session store instance
440
"""
441
```
442
443
### Static Files Handling
444
445
Static file collection, serving, and management utilities.
446
447
```python { .api }
448
# Static Files Finders
449
class BaseFinder:
450
"""
451
Base class for static file finders.
452
453
Abstract interface for locating static files from various sources.
454
"""
455
def find(self, path: str, all: bool = False) -> str: ...
456
def list(self, ignore_patterns: list) -> list: ...
457
458
class FileSystemFinder(BaseFinder):
459
"""
460
Finder for static files in STATICFILES_DIRS.
461
462
Locates files from configured static directories.
463
"""
464
465
class AppDirectoriesFinder(BaseFinder):
466
"""
467
Finder for static files in app directories.
468
469
Locates files from 'static' folders in installed apps.
470
"""
471
472
class DefaultStorageFinder(BaseFinder):
473
"""
474
Finder using default file storage backend.
475
476
Locates files from configured default storage.
477
"""
478
479
# Static Files Storage
480
class StaticFilesStorage(FileSystemStorage):
481
"""
482
File storage for collected static files.
483
484
Standard storage backend for static file collection.
485
"""
486
487
class ManifestStaticFilesStorage(StaticFilesStorage):
488
"""
489
Static files storage with manifest-based versioning.
490
491
Adds file hashing and manifest generation for cache busting.
492
"""
493
manifest_version: str = '1.0'
494
manifest_name: str = 'staticfiles.json'
495
manifest_strict: bool = True
496
497
def __init__(self, location: str = None, base_url: str = None, file_permissions_mode: int = None,
498
directory_permissions_mode: int = None, manifest_storage=None): ...
499
def hashed_name(self, name: str, content=None, filename: str = None) -> str: ...
500
def url(self, name: str, force: bool = False) -> str: ...
501
def load_manifest(self) -> dict: ...
502
def save_manifest(self) -> None: ...
503
504
class CachedStaticFilesStorage(ManifestStaticFilesStorage):
505
"""
506
Deprecated alias for ManifestStaticFilesStorage.
507
"""
508
509
# Static Files Management
510
def collect_static_files(verbosity: int = 1, interactive: bool = True, dry_run: bool = False,
511
clear: bool = False, link: bool = False, use_default_ignore_patterns: bool = True,
512
ignore_patterns: list = None) -> dict:
513
"""
514
Collect static files from all configured sources.
515
516
Args:
517
verbosity: Output verbosity level
518
interactive: Whether to prompt for user input
519
dry_run: Show actions without executing
520
clear: Clear existing files before collecting
521
link: Create symbolic links instead of copying
522
use_default_ignore_patterns: Use default ignore patterns
523
ignore_patterns: Additional patterns to ignore
524
525
Returns:
526
Dictionary of collection statistics
527
"""
528
529
def get_finders() -> list:
530
"""
531
Get list of configured static file finders.
532
533
Returns:
534
List of finder instances
535
"""
536
537
def find_static_file(path: str, all: bool = False) -> str:
538
"""
539
Find static file using configured finders.
540
541
Args:
542
path: Static file path to find
543
all: Return all matches instead of first
544
545
Returns:
546
File path or list of paths if all=True
547
"""
548
549
# Static Files Template Tags
550
def static(path: str) -> str:
551
"""
552
Template tag for generating static file URLs.
553
554
Args:
555
path: Static file path
556
557
Returns:
558
Full URL to static file
559
"""
560
561
def get_static_prefix() -> str:
562
"""
563
Template tag for getting static files URL prefix.
564
565
Returns:
566
STATIC_URL setting value
567
"""
568
569
def get_media_prefix() -> str:
570
"""
571
Template tag for getting media files URL prefix.
572
573
Returns:
574
MEDIA_URL setting value
575
"""
576
```
577
578
### Sites Framework
579
580
Multi-site support for sharing Django projects across domains.
581
582
```python { .api }
583
class Site(models.Model):
584
"""
585
Model representing a website/domain in multi-site setup.
586
587
Associates content and configuration with specific domains.
588
"""
589
domain: models.CharField
590
name: models.CharField
591
592
objects: SiteManager
593
594
def __str__(self) -> str: ...
595
def natural_key(self) -> tuple: ...
596
def get_absolute_url(self) -> str: ...
597
598
class SiteManager(models.Manager):
599
"""
600
Manager for Site model with caching support.
601
"""
602
use_in_migrations: bool = True
603
604
def get_current(self, request: HttpRequest = None) -> Site: ...
605
def clear_cache(self) -> None: ...
606
def get_by_natural_key(self, domain: str) -> Site: ...
607
608
def get_current_site(request: HttpRequest) -> Site:
609
"""
610
Get current site from request.
611
612
Args:
613
request: HTTP request object
614
615
Returns:
616
Current Site instance
617
"""
618
```
619
620
### Messages Framework
621
622
User messaging system for displaying notifications and alerts.
623
624
```python { .api }
625
# Message Levels
626
DEBUG: int = 10
627
INFO: int = 20
628
SUCCESS: int = 25
629
WARNING: int = 30
630
ERROR: int = 40
631
632
DEFAULT_LEVELS: dict = {
633
DEBUG: 'debug',
634
INFO: 'info',
635
SUCCESS: 'success',
636
WARNING: 'warning',
637
ERROR: 'error',
638
}
639
640
# Message Classes
641
class Message:
642
"""
643
Individual message with level and content.
644
645
Represents a single notification or alert for users.
646
"""
647
def __init__(self, level: int, message: str, extra_tags: str = ''): ...
648
def _prepare(self) -> None: ...
649
def __str__(self) -> str: ...
650
def __eq__(self, other) -> bool: ...
651
652
level: int
653
message: str
654
extra_tags: str
655
level_tag: str
656
657
class MessageFailure(Exception):
658
"""
659
Exception raised when message cannot be added.
660
"""
661
662
# Message Storage Backends
663
class BaseStorage:
664
"""
665
Base message storage backend.
666
667
Abstract interface for storing user messages across requests.
668
"""
669
request: HttpRequest
670
671
def __init__(self, request: HttpRequest): ...
672
def __len__(self) -> int: ...
673
def __iter__(self): ...
674
def __contains__(self, item: Message) -> bool: ...
675
def add(self, level: int, message: str, extra_tags: str = '') -> None: ...
676
def _get_level(self) -> int: ...
677
def _set_level(self, value: int) -> None: ...
678
def _store(self, messages: list, response: HttpResponse, *args, **kwargs) -> None: ...
679
def _get(self, *args, **kwargs) -> tuple: ...
680
def update(self, response: HttpResponse) -> None: ...
681
682
level: int
683
684
class SessionStorage(BaseStorage):
685
"""
686
Session-based message storage.
687
688
Stores messages in user session data.
689
"""
690
session_key: str = '_messages'
691
692
class CookieStorage(BaseStorage):
693
"""
694
Cookie-based message storage.
695
696
Stores messages in signed browser cookies.
697
"""
698
cookie_name: str = 'messages'
699
max_cookie_size: int = 2048
700
701
class FallbackStorage(BaseStorage):
702
"""
703
Combined session and cookie storage with fallback.
704
705
Uses session storage with cookie fallback for reliability.
706
"""
707
storage_classes: tuple = (CookieStorage, SessionStorage)
708
709
# Message Functions
710
def add_message(request: HttpRequest, level: int, message: str, extra_tags: str = '', fail_silently: bool = False) -> None:
711
"""
712
Add message to request.
713
714
Args:
715
request: HTTP request object
716
level: Message level (DEBUG, INFO, SUCCESS, WARNING, ERROR)
717
message: Message content
718
extra_tags: Additional CSS classes
719
fail_silently: Don't raise exception on failure
720
"""
721
722
def get_messages(request: HttpRequest) -> list:
723
"""
724
Get messages from request storage.
725
726
Args:
727
request: HTTP request object
728
729
Returns:
730
List of Message objects
731
"""
732
733
def debug(request: HttpRequest, message: str, extra_tags: str = '', fail_silently: bool = False) -> None:
734
"""Add debug message."""
735
736
def info(request: HttpRequest, message: str, extra_tags: str = '', fail_silently: bool = False) -> None:
737
"""Add info message."""
738
739
def success(request: HttpRequest, message: str, extra_tags: str = '', fail_silently: bool = False) -> None:
740
"""Add success message."""
741
742
def warning(request: HttpRequest, message: str, extra_tags: str = '', fail_silently: bool = False) -> None:
743
"""Add warning message."""
744
745
def error(request: HttpRequest, message: str, extra_tags: str = '', fail_silently: bool = False) -> None:
746
"""Add error message."""
747
748
def get_level(request: HttpRequest) -> int:
749
"""
750
Get minimum message level for request.
751
752
Args:
753
request: HTTP request object
754
755
Returns:
756
Current message level
757
"""
758
759
def set_level(request: HttpRequest, level: int) -> None:
760
"""
761
Set minimum message level for request.
762
763
Args:
764
request: HTTP request object
765
level: New message level
766
"""
767
768
# Message Middleware
769
class MessageMiddleware:
770
"""
771
Middleware for processing user messages.
772
773
Handles message storage and retrieval across requests.
774
"""
775
def __init__(self, get_response): ...
776
def __call__(self, request: HttpRequest) -> HttpResponse: ...
777
def process_response(self, request: HttpRequest, response: HttpResponse) -> HttpResponse: ...
778
```
779
780
### Content Types Framework
781
782
Generic relations and content type introspection.
783
784
```python { .api }
785
class ContentType(models.Model):
786
"""
787
Model representing installed Django model types.
788
789
Provides generic foreign key support and model introspection.
790
"""
791
app_label: models.CharField
792
model: models.CharField
793
794
objects: ContentTypeManager
795
796
def __str__(self) -> str: ...
797
def name(self) -> str: ...
798
def model_class(self): ...
799
def get_object_for_this_type(self, **kwargs): ...
800
def get_all_objects_for_this_type(self, **kwargs): ...
801
def natural_key(self) -> tuple: ...
802
803
class ContentTypeManager(models.Manager):
804
"""
805
Manager for ContentType with caching and lookup methods.
806
"""
807
use_in_migrations: bool = True
808
809
def get_for_model(self, model, for_concrete_model: bool = True) -> ContentType: ...
810
def get_for_models(self, *models, for_concrete_models: bool = True) -> dict: ...
811
def get_by_natural_key(self, app_label: str, model: str) -> ContentType: ...
812
def clear_cache(self) -> None: ...
813
814
# Generic Foreign Keys
815
class GenericForeignKey:
816
"""
817
Generic foreign key to any model type.
818
819
Provides flexible relationships using content types.
820
"""
821
def __init__(self, ct_field: str = 'content_type', fk_field: str = 'object_id', for_concrete_model: bool = True): ...
822
823
def get_content_type(self, obj=None, id=None, using: str = None) -> ContentType: ...
824
def get_cached_value(self, instance, default=None): ...
825
def set_cached_value(self, instance, value) -> None: ...
826
def is_cached(self, instance) -> bool: ...
827
828
class GenericRelation(models.ForeignKey):
829
"""
830
Reverse generic foreign key relationship.
831
832
Provides reverse access to generic foreign key relationships.
833
"""
834
def __init__(self, to: str, object_id_field: str = 'object_id', content_type_field: str = 'content_type',
835
for_concrete_model: bool = True, related_query_name: str = None, limit_choices_to: dict = None, **kwargs): ...
836
837
# Generic Inline Admin
838
class GenericInlineModelAdmin:
839
"""
840
Admin interface for generic foreign key relationships.
841
"""
842
ct_field: str = 'content_type'
843
ct_fk_field: str = 'object_id'
844
formset = None
845
846
def get_formset(self, request: HttpRequest, obj=None, **kwargs): ...
847
848
class GenericStackedInline(GenericInlineModelAdmin):
849
"""
850
Stacked layout for generic inline admin.
851
"""
852
template: str = 'admin/edit_inline/stacked.html'
853
854
class GenericTabularInline(GenericInlineModelAdmin):
855
"""
856
Tabular layout for generic inline admin.
857
"""
858
template: str = 'admin/edit_inline/tabular.html'
859
```
860
861
### Humanize Filters
862
863
Template filters for human-friendly data formatting.
864
865
```python { .api }
866
def apnumber(value: int) -> str:
867
"""
868
Convert numbers 1-9 to Associated Press style.
869
870
Args:
871
value: Number to convert
872
873
Returns:
874
AP style number or original if > 9
875
"""
876
877
def intcomma(value: int) -> str:
878
"""
879
Add commas to integer for thousands separation.
880
881
Args:
882
value: Number to format
883
884
Returns:
885
Number with comma separators
886
"""
887
888
def intword(value: int) -> str:
889
"""
890
Convert large integers to human-readable format.
891
892
Args:
893
value: Number to convert
894
895
Returns:
896
Human-readable number (e.g., "1.2 million")
897
"""
898
899
def naturalday(value, arg: str = None) -> str:
900
"""
901
Convert date to natural language relative to today.
902
903
Args:
904
value: Date to convert
905
arg: Date format for non-today dates
906
907
Returns:
908
Natural language date ("today", "yesterday", "tomorrow")
909
"""
910
911
def naturaltime(value) -> str:
912
"""
913
Convert datetime to natural language relative to now.
914
915
Args:
916
value: Datetime to convert
917
918
Returns:
919
Natural language time ("2 hours ago", "in 3 minutes")
920
"""
921
922
def ordinal(value: int) -> str:
923
"""
924
Convert integer to ordinal form.
925
926
Args:
927
value: Number to convert
928
929
Returns:
930
Ordinal number string ("1st", "2nd", "3rd", "4th")
931
"""
932
```