Enhanced time synchronization for drf views.
12 commits
Clone ▾
| 43 B | |
| 1.0 KB | |
| 672 B | |
| 457 B | |
| 4.8 KB |
README.md
TimeCheck
TimeCheck is a Django REST Framework (DRF) extension that wraps the standard Request with first-class support for timestamp-based synchronization.
It adds a structured way to compare client and server timestamps, detect when updates are needed, and manage API headers in a consistent, testable manner.
Features
- 🧠
TimeCheck: context-aware timestamp diff logic (raise_get, etc.) - ⚙️ Configurable via
TimeCheckConf(env vars orsettings.TIMECHECK_CONF) - 🔒 Built-in error handling for missing or invalid timestamps
Installation
pip install git+https://github.com/huncholane/django-timecheck
Usage
Example View
from timecheck import TimeCheck
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.views import APIView
from .models import MyModel
class MyView(APIView):
def get(request: Request, pk:int):
instance = MyModel.objects.get(pk=pk)
TimeCheck(request,instance).check_time() # throws rest framework exception
...
return Response(data)
def put(request: Request, pk:int):
instance = MyModel.objects.get(pk=pk)
TimeCheck(request,instance).check_update() # throws rest framework exception
...
return Response(data)
Parameters
TimeCheck(request, ...) has the following arguments:
- request
rest_framework.request.Request: A request to extract the client timestamp from. (required) - instance
models.Model: The database instance to extract the server timestamp from using the instance field. (optional) - server_timestamp
dt.datetime: A manual server timestamp to override TimeCheck parsing.(optional) - client_timestamp
dt.datetime: A manual client timestamp to override TimeCheck parsing. (optional) - header_field
str: Field to find client timestamp in the header (defaults to config) - body_field
str: Field to find client timestamp in request body (defaults to config) - instance_field
str: Field to find server timestamp in database model (defaults to config) - missing_action:
"noupdate" | "continue"(defaults to config)noupdatewill raise a drf exception to indicate the view should stop early if the client does not provide a timestampcontinueallows the view to continue processing data when the client does not provide a timestamp
- noupdate_code
intThe response code for exceptions raised to indicate the view should stop processing - dt_fmt
strThe datetime format used to normalize timestamps. Useful when the client and server use mismatched time depths (defaults to config)
TimeCheck Methods
check_getRaises aNoUpdateexception when the client timestamp is newer than or equal to the server timestampraise_updateRaises aNoUpdateexception when the client timestamp is older than or equal to the server timestamp
Configuration
TimeCheck is customizable through the django settings, env, and on a per usage basis.
Django Settings Dictionairy Defaults
TIMECHECK_CONF = {
"body_field": "lastUpdated",
"dt_fmt": "%Y-%m-%dT%H:%M:%S%z",
"header_field": "lastUpdated",
"instance_field": "lastUpdated",
"missing_action": "noupdate",
"noupdate_code": 418,
}
Set via environment variables or in settings.PLUSREQUEST_CONF:
| Key | Default | Description |
|---|---|---|
TIMECHECK_HEADER_FIELD |
lastUpdated |
Header field used for client timestamp (str) |
TIMECHECK_BODY_FIELD |
lastUpdated |
Body field used for client timestamp (str) |
TIMECHECK_INSTANCE_FIELD |
lastUpdated |
Model field used for server timestamp (str) |
TIMECHECK_NOUPDATE_CODE |
418 |
Error code raised when update is unnecessary (int) |
TIMECHECK_MISSING_ACTION |
noupdate |
Action if timestamp is missing (continue, noupdate) |
TIMECHECK_DT_FMT |
%Y-%m-%dT%H:%M:%S%z |
Timestamp parsing format (str) |
Exceptions
InvalidClientDatetimeField (400)When the client timestamp is found but cannot be parsed.InvalidServerDatetimeField (500)When the server cannot make up a timestamp.NoUpdate (Custom)Custom status code used to represent no update.
Raised when timestamps are missing, malformatted, or update should be skipped.
License
This project is licensed under the MIT License.