Skip to content

DEV-687 Implement save calendar events#29

Open
asze17 wants to merge 6 commits into
previewfrom
save-calendar-events
Open

DEV-687 Implement save calendar events#29
asze17 wants to merge 6 commits into
previewfrom
save-calendar-events

Conversation

@asze17

@asze17 asze17 commented Apr 2, 2026

Copy link
Copy Markdown
Member

References

Proposed Changes

  • Add saved_by as a ManyToManyField under Event
  • Add a new View user_saved_events_view for new routes.

@asze17 asze17 requested a review from jfmath04 April 2, 2026 01:20
@linear

linear Bot commented Apr 2, 2026

Copy link
Copy Markdown

@ZhaoSongZh7 ZhaoSongZh7 left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change "unsave" to "delete" in user_saved_events_view.py. Maybe implement helper method for reducing the repetition of the error checking.

@jfmath04 jfmath04 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I left a few comments to review

Comment on lines +40 to +46
is_saved = serializers.SerializerMethodField()

def get_is_saved(self, obj: Event) -> bool:
user = self.context["request"].user

return obj.saved_by.contains(user)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will trigger a query per event when serializing to get whether the user saved the event. Can we do a query set annotation instead where we take the events we want to serialize, make a query to add the is_saved field into the query set, and then put the annotated query set into the serializer? This way we only make one query for all the events we want to serialize. Make sure all of the calls to the Event Serializer are updated to reflect changes (merge from preview first).


try:
event = Event.objects.get(pk=validated_data["event_id"])
event.saved_by.add(request.user)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should be delete

from rest_framework.response import Response
from rest_framework.views import APIView

from hoagiecalendar.api.user_events_view import EventSerializer

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

import from event_views

except Event.DoesNotExist:
return Response({"error": "event not found"}, status=status.HTTP_404_NOT_FOUND)
except Exception as e:
return Response({"error": f"an error occured while saving event for user: {e}"})

@jfmath04 jfmath04 Apr 28, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this needs a status 500.

also, can we leave out the actual error e and just return that there was an internal error? Write a TODO comment to log the error detail once we add logging.

except Event.DoesNotExist:
return Response({"error": "event not found"}, status=status.HTTP_404_NOT_FOUND)
except Exception as e:
return Response({"error": f"an error occured while unsaving event for user: {e}"})

@jfmath04 jfmath04 Apr 28, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this also needs a status 500.

also, can we leave out the actual error e and just return that there was an internal error? Write a TODO comment to log the error detail once we add logging.

event = Event.objects.get(pk=validated_data["event_id"])
event.saved_by.add(request.user)

return Response({"message": "event saved"}, status=status.HTTP_201_CREATED)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's return the updated event serialized here with status 200 since no new object was created.

event = Event.objects.get(pk=validated_data["event_id"])
event.saved_by.add(request.user)

return Response({"message": "event unsaved"}, status=status.HTTP_200_OK)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be status 204. Also no message needed since there is no data to return.

Comment thread backend/test_models.py

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you make a tests folder and put this in there? also delete the existing test.py file.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That wasn't meant to be committed. I can remove it for now and then add a more thorough test case later.

def post(self, request: Request) -> Response:
serializer = SaveEventRequestSerializer(data=request.data)
if not serializer.is_valid():
return Response({"error": serializer.errors}, status=status.HTTP_400_BAD_REQUEST)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

serializer.errors doesn't need to be nested in the dict. just put it in directly

def delete(self, request: Request) -> Response:
serializer = SaveEventRequestSerializer(data=request.data)
if not serializer.is_valid():
return Response({"error": serializer.errors}, status=status.HTTP_400_BAD_REQUEST)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

serializer.errors doesn't need to be nested in the dict. just put it in directly

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants