popoto.fields.datetime_field¶
popoto.fields.datetime_field
¶
Datetime field for storing Python datetime objects in Redis.
This module provides DatetimeField, a specialized field type that extends the base Field class to handle datetime values with automatic timestamp management. It follows Django's familiar auto_now and auto_now_add patterns, making it intuitive for developers transitioning from Django ORM to Popoto's Redis-based persistence.
The DatetimeField is central to the Timestampable mixin pattern, enabling models to automatically track creation and modification times without manual intervention.
Example usage
class Article(popoto.Model): title = popoto.KeyField() published_at = popoto.DatetimeField(null=True) created_at = popoto.DatetimeField(auto_now_add=True) updated_at = popoto.DatetimeField(auto_now=True)
Design note: Unlike shortcuts.py fields (DateField, TimeField) which are simple type wrappers, DatetimeField lives in its own module because it introduces behavioral logic (auto_now/auto_now_add) beyond just type enforcement.
DatetimeField
¶
Bases: Field
A field for storing datetime values with optional automatic timestamp management.
DatetimeField provides Django-compatible auto_now and auto_now_add functionality for Redis-persisted models. This design decision prioritizes developer familiarity over Redis-native timestamp patterns, reducing cognitive overhead when migrating from or working alongside Django projects.
The field automatically handles serialization through msgpack (via the parent Field class), storing datetime objects as ISO format strings in Redis.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
auto_now_add
|
Set to current datetime on first save only. |
required | |
auto_now
|
Update to current datetime on every save. |
required |
Attributes:
| Name | Type | Description |
|---|---|---|
auto_now_add |
bool
|
When True, automatically sets the field to the current datetime on first save only. Useful for created_at timestamps. |
auto_now |
bool
|
When True, automatically updates the field to the current datetime on every save. Useful for updated_at timestamps. |
Example
Track when a user was created and last modified¶
class User(popoto.Model): username = popoto.KeyField() created_at = popoto.DatetimeField(auto_now_add=True) last_seen = popoto.DatetimeField(auto_now=True)
Or use the built-in Timestampable mixin for the common pattern¶
from popoto.utils.mixins import Timestampable
class User(Timestampable): username = popoto.KeyField()
Source code in src/popoto/fields/datetime_field.py
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | |
format_value_pre_save(field_value, skip_auto_now=False, **kwargs)
¶
Apply automatic timestamp logic before persisting to Redis.
This method is called by the model's save pipeline, allowing DatetimeField to intercept and modify the value based on auto_now and auto_now_add settings. The hook pattern (format_value_pre_save) enables field-specific transformation logic without coupling to the model's save implementation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
field_value
|
The current datetime value, or None if not set. |
required | |
skip_auto_now
|
If True, suppress auto_now timestamp updates. Useful for data migrations where existing timestamps should be preserved. Does not affect auto_now_add behavior. |
False
|
|
**kwargs
|
Additional keyword arguments for forward compatibility. |
{}
|
Returns:
| Name | Type | Description |
|---|---|---|
datetime |
The processed datetime value. Returns the current UTC time for auto_now fields (unless skip_auto_now is True), the current UTC time for auto_now_add when field_value is falsy, or the original field_value otherwise. |
Implementation note
Timestamps are stamped in UTC via datetime.now(timezone.utc) so
that auto_now/auto_now_add fields record correct instants regardless
of host timezone. (The encoder stores wall-clock without tzinfo, so
consumers re-attach UTC on read.) timezone.utc is used rather than
datetime.UTC to stay valid on Python 3.10 (the requires-python
floor); datetime.UTC is 3.11+.
auto_now takes precedence if both flags are set, as it unconditionally returns the current UTC time regardless of existing value (unless skipped).