0

I am writing an API endpoint that queries for an Event in the time window given.

The Event model has a start and end time, and the query accepts a search start time and an search end time. Any Event that overlaps between these two windows is returned. This works well.

However, if the user asks to search using a search_time_start that is after the search_time_end, it returns no results (obviously), with no indication why.

Instead I would like to return an Error message indicating what is wrong.

I have a rough idea of how to do this, but not how to plug it into my existing code.

Model

class Event(models.Model):

    name = model.CharField(max_length=64)

    start_time = models.DateTimeField(null=False)

    end_time = models.DateTimeField(null=False)

Serializer

class EventSerializer(serializers.ModelSerializer):
    start_time = serializers.DateTimeField()
    end_time = serializers.DateTimeField()

    class Meta:
        model = Event
        fields = ("start_time", "end_time")

Filter and View

class EventFilterSet(GeoFilterSet):

    search_time_start = DateTimeFilter(
        field_name="end_time",
        lookup_expr="gte",
        help_text=(
            "The time for the start of the search. Limits events to those that end after the start time."
        ),
    )
    search_time_end = DateTimeFilter(
        field_name="start_time",
        lookup_expr="lte",
        help_text=(
            "The time for the end of the search. Limits events to those that start before the end time."
        ),
    )

    class Meta:
        model = Event
        fields = ["search_time_start", "search_time_end"]


class BaseEventViewSet(GenericViewSet):
    queryset = Event.objects.all()
    serializer_class = EventSerializer
    filterset_class = EventFilterSet
    ordering = ("start_time",)

I have written this snippet which I think should work, but I am unsure if it should go in a view or serializer, and how to make sure the method is actually called. I suspect I may be incorrectly mixing Class-based View and Function-based views here... so perhaps there's a better way to accomplish this.

    def check_valid_start_end_search(self, request):
        start = request.query_params.get("start_time")
        end = request.query_params.get("end_time")

        if not start < end:
            return Response({"error": "The start time must be after the end time"}, status=HTTP_400_BAD_REQUEST)

I've seen some similar quesitons here, but they all deal with function-based views or handling the same error but on a model field, not a query param

Brian C
  • 1,333
  • 3
  • 19
  • 36

1 Answers1

0

You can raise custom errors from your serializers also to validate start time and end time.
try this solution.

class EventSerializer(serializers.ModelSerializer):
    start_time = serializers.DateTimeField()
    end_time = serializers.DateTimeField()

    class Meta:
        model = Event
        fields = ("start_time", "end_time")

    def validate(self,attrs):
        start_time=attrs.get('start_time')
        end_time=attrs.get('end_time')
        if start_time < end_time:
            raise serializers.ValidationError('The start time must be after the end time')
        return attrs
  • I tried this, but the `validate()` method is never actually called. Additionally, I want to compare the parameters passed to the API to filter the query, (defined in the FilterSet), wouldn't this be validating the start/end time on the model fields for the event? Not for the query to look up events? – Brian C Nov 10 '22 at 23:20