diff --git a/bugsink/api_serializers.py b/bugsink/api_serializers.py new file mode 100644 index 0000000..d50f8da --- /dev/null +++ b/bugsink/api_serializers.py @@ -0,0 +1,13 @@ +import datetime +from rest_framework import serializers + + +class UTCModelSerializer(serializers.ModelSerializer): + + def build_standard_field(self, field_name, model_field): + field_class, field_kwargs = super().build_standard_field(field_name, model_field) + + if field_class is serializers.DateTimeField: + field_kwargs.setdefault("default_timezone", datetime.timezone.utc) + + return field_class, field_kwargs diff --git a/events/serializers.py b/events/serializers.py index dad6b6a..92f1827 100644 --- a/events/serializers.py +++ b/events/serializers.py @@ -1,11 +1,12 @@ from rest_framework import serializers from drf_spectacular.utils import extend_schema_field +from bugsink.api_serializers import UTCModelSerializer from .markdown_stacktrace import render_stacktrace_md from .models import Event -class EventListSerializer(serializers.ModelSerializer): +class EventListSerializer(UTCModelSerializer): """Lightweight list view: excludes the (potentially large) `data` field.""" class Meta: @@ -23,7 +24,7 @@ class EventListSerializer(serializers.ModelSerializer): ] -class EventDetailSerializer(serializers.ModelSerializer): +class EventDetailSerializer(UTCModelSerializer): """Detail view: includes full `data` payload.""" # NOTE as with Issue.grouping_keys: check viewset for prefetching # grouping_key = serializers.CharField(source="grouping.grouping_key", read_only=True) diff --git a/issues/serializers.py b/issues/serializers.py index a8e482f..e07f67e 100644 --- a/issues/serializers.py +++ b/issues/serializers.py @@ -1,9 +1,9 @@ -from rest_framework import serializers +from bugsink.api_serializers import UTCModelSerializer from .models import Issue -class IssueSerializer(serializers.ModelSerializer): +class IssueSerializer(UTCModelSerializer): # grouping_keys = serializers.SerializerMethodField() # read-only list of strings class Meta: diff --git a/projects/serializers.py b/projects/serializers.py index df5d824..3621b8c 100644 --- a/projects/serializers.py +++ b/projects/serializers.py @@ -1,4 +1,5 @@ from rest_framework import serializers +from bugsink.api_serializers import UTCModelSerializer from bugsink.api_fields import make_enum_field from teams.models import Team @@ -11,7 +12,7 @@ from .models import Project, ProjectVisibility ProjectVisibilityField = make_enum_field(ProjectVisibility) -class ProjectListSerializer(serializers.ModelSerializer): +class ProjectListSerializer(UTCModelSerializer): visibility = ProjectVisibilityField() dsn = serializers.CharField(read_only=True) @@ -33,7 +34,7 @@ class ProjectListSerializer(serializers.ModelSerializer): ] -class ProjectDetailSerializer(ExpandableSerializerMixin, serializers.ModelSerializer): +class ProjectDetailSerializer(ExpandableSerializerMixin, UTCModelSerializer): expandable_fields = {"team": TeamDetailSerializer} visibility = ProjectVisibilityField() dsn = serializers.CharField(read_only=True) @@ -56,7 +57,7 @@ class ProjectDetailSerializer(ExpandableSerializerMixin, serializers.ModelSerial ] -class ProjectCreateUpdateSerializer(serializers.ModelSerializer): +class ProjectCreateUpdateSerializer(UTCModelSerializer): id = serializers.UUIDField(read_only=True) team = serializers.PrimaryKeyRelatedField(queryset=Team.objects.all()) visibility = ProjectVisibilityField(required=False) diff --git a/releases/serializers.py b/releases/serializers.py index 4b82227..6fb6065 100644 --- a/releases/serializers.py +++ b/releases/serializers.py @@ -1,5 +1,7 @@ +import datetime from django.utils import timezone from rest_framework import serializers +from bugsink.api_serializers import UTCModelSerializer from projects.models import Project from rest_framework.exceptions import ValidationError @@ -7,13 +9,13 @@ from rest_framework.exceptions import ValidationError from .models import Release, create_release_if_needed -class ReleaseListSerializer(serializers.ModelSerializer): +class ReleaseListSerializer(UTCModelSerializer): class Meta: model = Release fields = ["id", "project", "version", "date_released"] -class ReleaseDetailSerializer(serializers.ModelSerializer): +class ReleaseDetailSerializer(UTCModelSerializer): class Meta: model = Release fields = ["id", "project", "version", "date_released", "semver", "is_semver", "sort_epoch"] @@ -23,7 +25,7 @@ class ReleaseDetailSerializer(serializers.ModelSerializer): class ReleaseCreateSerializer(serializers.Serializer): project = serializers.PrimaryKeyRelatedField(queryset=Project.objects.all()) version = serializers.CharField(allow_blank=True) - timestamp = serializers.DateTimeField(required=False) + timestamp = serializers.DateTimeField(required=False, default_timezone=datetime.timezone.utc) def create(self, validated_data): project = validated_data["project"] diff --git a/teams/serializers.py b/teams/serializers.py index 7e15b38..2e617e0 100644 --- a/teams/serializers.py +++ b/teams/serializers.py @@ -1,12 +1,13 @@ from rest_framework import serializers from bugsink.api_fields import make_enum_field +from bugsink.api_serializers import UTCModelSerializer from .models import Team, TeamVisibility TeamVisibilityField = make_enum_field(TeamVisibility) -class TeamListSerializer(serializers.ModelSerializer): +class TeamListSerializer(UTCModelSerializer): visibility = TeamVisibilityField() class Meta: @@ -14,7 +15,7 @@ class TeamListSerializer(serializers.ModelSerializer): fields = ["id", "name", "visibility"] -class TeamDetailSerializer(serializers.ModelSerializer): +class TeamDetailSerializer(UTCModelSerializer): visibility = TeamVisibilityField() class Meta: @@ -22,7 +23,7 @@ class TeamDetailSerializer(serializers.ModelSerializer): fields = ["id", "name", "visibility"] -class TeamCreateUpdateSerializer(serializers.ModelSerializer): +class TeamCreateUpdateSerializer(UTCModelSerializer): id = serializers.UUIDField(read_only=True) visibility = TeamVisibilityField(required=False)