Event Timeline
That code is too hackish from my point of view, modifying internal private member of a class from the outside is never a good idea in programming.
I think the best way to implement the feature is (as pointed by @vlorentz in a D7491 inline comment) to directly add the new moderator and last_modified_date
field in the output produced by the AddForgeNowRequest*Serializer classes.
Below is an example of adding the new fields to the output produced by AddForgeNowRequestPublicSerializer you can inspire from.
class AddForgeNowRequestPublicSerializer(serializers.ModelSerializer): """Serializes AddForgeRequest without private fields.""" moderator = serializers.SerializerMethodField() last_modified_date = serializers.SerializerMethodField() history = None class Meta: model = AddForgeRequest fields = ( "id", "forge_url", "forge_type", "status", "submission_date", "moderator", "last_modified_date", ) def _get_history(self, request): if not self.history: self.history = AddForgeNowRequestHistory.objects.filter( request=request ).order_by("id") return self.history def get_moderator(self, request): last_history_with_moderator = ( self._get_history(request).filter(actor_role="MODERATOR").last() ) return ( last_history_with_moderator.actor if last_history_with_moderator else None ) def get_last_modified_date(self, request): last_history = self._get_history(request).last() return ( last_history.date.isoformat().replace("+00:00", "Z") if last_history else None )
The adding of these fields should also be done for the private AddForgeNowRequestSerializer class (without too much code duplication if possible).
I'm having some trouble understanding the behaviour of serializers:
if has_add_forge_now_permission(request.user): for item in page.object_list: print(AddForgeNowRequestSerializer(item).data) print() requests = AddForgeNowRequestSerializer(page.object_list, many=True).data for req in requests: print(dict(req)) print()
class AddForgeNowRequestSerializer(serializers.ModelSerializer): moderator = serializers.SerializerMethodField() last_modified_date = serializers.SerializerMethodField() history = None class Meta: model = AddForgeRequest fields = "__all__" def _gethistory(self, request): if not self.history: self.history = AddForgeNowRequestHistory.objects.filter( request=request ).order_by("id") return self.history def get_moderator(self, request): last_history_with_moderator = self._gethistory(request).filter(actor_role = "MODERATOR").last() print("MODERATOR: ", last_history_with_moderator.actor) if last_history_with_moderator else print("MODERATOR: None") return last_history_with_moderator.actor if last_history_with_moderator else None def get_last_modified_date(self, request): last_history = self._gethistory(request).last() return last_history.date.isoformat().replace("+00:00", "Z") if last_history else None
The output of this block is:
MODERATOR: None {'id': 1, 'moderator': None, 'last_modified_date': '2022-04-01T15:58:40.348874Z', 'status': 'PENDING', 'submission_date': '2022-04-01T15:58:40.346816Z', 'submitter_name': 'admin', 'submitter_email': 'admin@swh-web.org', 'submitter_forward_username': True, 'forge_type': 'bitbucket', 'forge_url': 'http://examplelink.com', 'forge_contact_email': 'example@email.com', 'forge_contact_name': 'Admin', 'forge_contact_comment': 'Comment'} MODERATOR: admin {'id': 2, 'moderator': 'admin', 'last_modified_date': '2022-04-27T14:29:21.215613Z', 'status': 'WAITING_FOR_FEEDBACK', 'submission_date': '2022-04-01T16:00:07.419837Z', 'submitter_name': 'admin', 'submitter_email': 'admin@swh-web.org', 'submitter_forward_username': True, 'forge_type': 'bitbucket', 'forge_url': 'http://examplelink2.com', 'forge_contact_email': 'example@email.com', 'forge_contact_name': 'Admin', 'forge_contact_comment': 'a'} MODERATOR: admin {'id': 3, 'moderator': 'admin', 'last_modified_date': '2022-04-27T15:34:34.263599Z', 'status': 'WAITING_FOR_FEEDBACK', 'submission_date': '2022-04-03T08:17:43.355030Z', 'submitter_name': 'admin', 'submitter_email': 'admin@swh-web.org', 'submitter_forward_username': True, 'forge_type': 'bitbucket', 'forge_url': 'https://google.com', 'forge_contact_email': 'testemail@gmail.com', 'forge_contact_name': 'Anirudh', 'forge_contact_comment': 'This is the final test entry'} MODERATOR: None MODERATOR: None MODERATOR: None {'id': 1, 'moderator': None, 'last_modified_date': '2022-04-01T15:58:40.348874Z', 'status': 'PENDING', 'submission_date': '2022-04-01T15:58:40.346816Z', 'submitter_name': 'admin', 'submitter_email': 'admin@swh-web.org', 'submitter_forward_username': True, 'forge_type': 'bitbucket', 'forge_url': 'http://examplelink.com', 'forge_contact_email': 'example@email.com', 'forge_contact_name': 'Admin', 'forge_contact_comment': 'Comment'} {'id': 2, 'moderator': None, 'last_modified_date': '2022-04-01T15:58:40.348874Z', 'status': 'WAITING_FOR_FEEDBACK', 'submission_date': '2022-04-01T16:00:07.419837Z', 'submitter_name': 'admin', 'submitter_email': 'admin@swh-web.org', 'submitter_forward_username': True, 'forge_type': 'bitbucket', 'forge_url': 'http://examplelink2.com', 'forge_contact_email': 'example@email.com', 'forge_contact_name': 'Admin', 'forge_contact_comment': 'a'} {'id': 3, 'moderator': None, 'last_modified_date': '2022-04-01T15:58:40.348874Z', 'status': 'WAITING_FOR_FEEDBACK', 'submission_date': '2022-04-03T08:17:43.355030Z', 'submitter_name': 'admin', 'submitter_email': 'admin@swh-web.org', 'submitter_forward_username': True, 'forge_type': 'bitbucket', 'forge_url': 'https://google.com', 'forge_contact_email': 'testemail@gmail.com', 'forge_contact_name': 'Anirudh', 'forge_contact_comment': 'This is the final test entry'}
Going by this,
The individually serialized objects work as expected, with the explicitly defined fields having the right values.
When the many=True flag is passed, the explicitly defined fields have wrong/default values.
I'm unable to find the cause for this behaviour, and request the help of the subscribers to ascertain the same.
This is due to the history cache that does not support multiple requests, use this to make it compatible with the many case:
class AddForgeNowRequestSerializer(serializers.ModelSerializer): moderator = serializers.SerializerMethodField() last_modified_date = serializers.SerializerMethodField() history: Dict[int, QuerySet] = {} class Meta: model = AddForgeRequest fields = "__all__" def _gethistory(self, request): if request.id not in self.history: self.history[request.id] = AddForgeNowRequestHistory.objects.filter( request=request ).order_by("id") return self.history[request.id] def get_moderator(self, request): last_history_with_moderator = ( self._gethistory(request).filter(actor_role="MODERATOR").last() ) print( "MODERATOR: ", last_history_with_moderator.actor ) if last_history_with_moderator else print("MODERATOR: None") return ( last_history_with_moderator.actor if last_history_with_moderator else None ) def get_last_modified_date(self, request): last_history = self._gethistory(request).last() return ( last_history.date.isoformat().replace("+00:00", "Z") if last_history else None )