diff --git a/apps/hosts/models.py b/apps/hosts/models.py index 5ed1a59587..6bdbcb8792 100644 --- a/apps/hosts/models.py +++ b/apps/hosts/models.py @@ -21,7 +21,7 @@ class ChallengeHostTeam(TimeStampedModel): team_url = models.CharField(max_length=1000, default="", blank=True) def __str__(self): - return "{0}: {1}".format(self.team_name, self.created_by) + return f"{self.team_name}: {self.created_by}" def get_all_challenge_host_email(self): email_ids = ChallengeHost.objects.filter(team_name=self).values_list( @@ -72,9 +72,7 @@ class ChallengeHost(TimeStampedModel): permissions = models.CharField(max_length=30, choices=PERMISSION_OPTIONS) def __str__(self): - return "{0}:{1}:{2}".format( - self.team_name, self.user, self.permissions - ) + return f"{self.team_name}:{self.user}:{self.permissions}" class Meta: app_label = "hosts" diff --git a/apps/hosts/serializers.py b/apps/hosts/serializers.py index cd1ade4b8e..e640ccb1e1 100644 --- a/apps/hosts/serializers.py +++ b/apps/hosts/serializers.py @@ -5,13 +5,14 @@ class ChallengeHostTeamSerializer(serializers.ModelSerializer): + """Serializer for the ChallengeHostTeam model.""" created_by = serializers.SlugRelatedField( slug_field="username", queryset=User.objects.all() ) def __init__(self, *args, **kwargs): - super(ChallengeHostTeamSerializer, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) context = kwargs.get("context") if context: request = context.get("request") @@ -23,6 +24,7 @@ class Meta: class ChallengeHostSerializer(serializers.ModelSerializer): + """Serializer for the ChallengeHost model.""" status = serializers.ChoiceField(choices=ChallengeHost.STATUS_OPTIONS) permissions = serializers.ChoiceField( @@ -33,7 +35,7 @@ class ChallengeHostSerializer(serializers.ModelSerializer): ) def __init__(self, *args, **kwargs): - super(ChallengeHostSerializer, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) context = kwargs.get("context") if context: challenge_host_team = context.get("challenge_host_team") @@ -47,26 +49,30 @@ class Meta: class InviteHostToTeamSerializer(serializers.Serializer): + """Serializer for inviting a host to join a team.""" email = serializers.EmailField() def __init__(self, *args, **kwargs): - super(InviteHostToTeamSerializer, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) context = kwargs.get("context") if context: self.challenge_host_team = context.get("challenge_host_team") self.user = context.get("request").user def validate_email(self, value): + """Validate the email to ensure it + doesn't belong to the inviting user.""" if value == self.user.email: raise serializers.ValidationError("A host cannot invite himself") try: User.objects.get(email=value) - except User.DoesNotExist: - raise serializers.ValidationError("User does not exist") + except User.DoesNotExist as exc: + raise serializers.ValidationError("User does not exist") from exc return value - def save(self): + def save(self, **kwargs): + """Create or get a ChallengeHost for the invited user.""" email = self.validated_data.get("email") return ChallengeHost.objects.get_or_create( user=User.objects.get(email=email), @@ -77,6 +83,7 @@ def save(self): class HostTeamDetailSerializer(serializers.ModelSerializer): + """Serializer for detailed information about host teams.""" members = serializers.SerializerMethodField() created_by = serializers.SlugRelatedField( @@ -87,7 +94,9 @@ class Meta: model = ChallengeHostTeam fields = ("id", "team_name", "created_by", "members", "team_url") - def get_members(self, obj): + @staticmethod + def get_members(obj): + """Get all members of a host team.""" hosts = ChallengeHost.objects.filter(team_name_id=obj.id) serializer = ChallengeHostSerializer(hosts, many=True) return serializer.data diff --git a/apps/hosts/urls.py b/apps/hosts/urls.py index 07ebc89c62..e4ea70eb62 100644 --- a/apps/hosts/urls.py +++ b/apps/hosts/urls.py @@ -19,17 +19,21 @@ name="create_challenge_host_team", ), url( - r"^challenge_host_team/(?P[0-9]+)/challenge_host$", + r"^challenge_host_team/" + r"(?P[0-9]+)/challenge_host$", views.challenge_host_list, name="get_challenge_host_list", ), url( - r"^challenge_host_team/(?P[0-9]+)/challenge_host/(?P[0-9]+)$", + r"^challenge_host_team/" + r"(?P[0-9]+)/" + r"challenge_host/(?P[0-9]+)$", views.challenge_host_detail, name="get_challenge_host_details", ), url( - r"^remove_self_from_challenge_host/(?P[0-9]+)$", + r"^remove_self_from_challenge_host/" + r"(?P[0-9]+)$", views.remove_self_from_challenge_host_team, name="remove_self_from_challenge_host_team", ), diff --git a/apps/hosts/views.py b/apps/hosts/views.py index c6e9cf48de..4bbe60ff2d 100644 --- a/apps/hosts/views.py +++ b/apps/hosts/views.py @@ -38,6 +38,12 @@ ) ) def challenge_host_team_list(request): + """ + Get or create challenge host teams. + + GET: List all challenge host teams for the authenticated user + POST: Create a new challenge host team + """ if request.method == "GET": challenge_host_team_ids = ChallengeHost.objects.filter( user=request.user @@ -55,15 +61,15 @@ def challenge_host_team_list(request): response_data = serializer.data return paginator.get_paginated_response(response_data) - elif request.method == "POST": - serializer = ChallengeHostTeamSerializer( - data=request.data, context={"request": request} - ) - if serializer.is_valid(): - serializer.save() - response_data = serializer.data - return Response(response_data, status=status.HTTP_201_CREATED) - return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + # POST method + serializer = ChallengeHostTeamSerializer( + data=request.data, context={"request": request} + ) + if serializer.is_valid(): + serializer.save() + response_data = serializer.data + return Response(response_data, status=status.HTTP_201_CREATED) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) @api_view(["GET", "PUT", "PATCH"]) @@ -71,6 +77,13 @@ def challenge_host_team_list(request): @permission_classes((permissions.IsAuthenticated, HasVerifiedEmail)) @authentication_classes((JWTAuthentication, ExpiringTokenAuthentication)) def challenge_host_team_detail(request, pk): + """ + Get, update or partially update a challenge host team. + + GET: Get details of a challenge host team + PUT: Update a challenge host team + PATCH: Partially update a challenge host team + """ try: challenge_host_team = ChallengeHostTeam.objects.get(pk=pk) except ChallengeHostTeam.DoesNotExist: @@ -82,29 +95,25 @@ def challenge_host_team_detail(request, pk): response_data = serializer.data return Response(response_data, status=status.HTTP_200_OK) - elif request.method in ["PUT", "PATCH"]: - - if request.method == "PATCH": - serializer = ChallengeHostTeamSerializer( - challenge_host_team, - data=request.data, - context={"request": request}, - partial=True, - ) - else: - serializer = ChallengeHostTeamSerializer( - challenge_host_team, - data=request.data, - context={"request": request}, - ) - if serializer.is_valid(): - serializer.save() - response_data = serializer.data - return Response(response_data, status=status.HTTP_200_OK) - else: - return Response( - serializer.errors, status=status.HTTP_400_BAD_REQUEST - ) + # PUT or PATCH methods + if request.method == "PATCH": + serializer = ChallengeHostTeamSerializer( + challenge_host_team, + data=request.data, + context={"request": request}, + partial=True, + ) + else: # PUT + serializer = ChallengeHostTeamSerializer( + challenge_host_team, + data=request.data, + context={"request": request}, + ) + if serializer.is_valid(): + serializer.save() + response_data = serializer.data + return Response(response_data, status=status.HTTP_200_OK) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) @api_view(["GET", "POST"]) @@ -112,7 +121,12 @@ def challenge_host_team_detail(request, pk): @permission_classes((permissions.IsAuthenticated, HasVerifiedEmail)) @authentication_classes((JWTAuthentication, ExpiringTokenAuthentication)) def challenge_host_list(request, challenge_host_team_pk): + """ + Get or create challenge hosts within a team. + GET: List all challenge hosts for a team + POST: Add a new challenge host to a team + """ try: challenge_host_team = ChallengeHostTeam.objects.get( pk=challenge_host_team_pk @@ -141,19 +155,19 @@ def challenge_host_list(request, challenge_host_team_pk): response_data = serializer.data return paginator.get_paginated_response(response_data) - elif request.method == "POST": - serializer = ChallengeHostSerializer( - data=request.data, - context={ - "challenge_host_team": challenge_host_team, - "request": request, - }, - ) - if serializer.is_valid(): - serializer.save() - response_data = serializer.data - return Response(response_data, status=status.HTTP_201_CREATED) - return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + # POST method + serializer = ChallengeHostSerializer( + data=request.data, + context={ + "challenge_host_team": challenge_host_team, + "request": request, + }, + ) + if serializer.is_valid(): + serializer.save() + response_data = serializer.data + return Response(response_data, status=status.HTTP_201_CREATED) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) @api_view(["GET", "PUT", "PATCH", "DELETE"]) @@ -161,6 +175,14 @@ def challenge_host_list(request, challenge_host_team_pk): @permission_classes((permissions.IsAuthenticated, HasVerifiedEmail)) @authentication_classes((JWTAuthentication, ExpiringTokenAuthentication)) def challenge_host_detail(request, challenge_host_team_pk, pk): + """ + Get, update, partially update or delete a challenge host. + + GET: Get details of a challenge host + PUT: Update a challenge host + PATCH: Partially update a challenge host + DELETE: Remove a challenge host + """ try: challenge_host_team = ChallengeHostTeam.objects.get( pk=challenge_host_team_pk @@ -176,46 +198,45 @@ def challenge_host_detail(request, challenge_host_team_pk, pk): response_data = serializer.data return Response(response_data, status=status.HTTP_200_OK) - elif request.method in ["PUT", "PATCH"]: - if request.method == "PATCH": - serializer = ChallengeHostSerializer( - challenge_host, - data=request.data, - context={ - "challenge_host_team": challenge_host_team, - "request": request, - }, - partial=True, - ) - else: - serializer = ChallengeHostSerializer( - challenge_host, - data=request.data, - context={ - "challenge_host_team": challenge_host_team, - "request": request, - }, - ) - if serializer.is_valid(): - serializer.save() - response_data = serializer.data - return Response(response_data, status=status.HTTP_200_OK) - else: - return Response( - serializer.errors, status=status.HTTP_400_BAD_REQUEST - ) - - elif request.method == "DELETE": + if request.method == "DELETE": challenge_host.delete() return Response(status=status.HTTP_204_NO_CONTENT) + # PUT or PATCH methods + if request.method == "PATCH": + serializer = ChallengeHostSerializer( + challenge_host, + data=request.data, + context={ + "challenge_host_team": challenge_host_team, + "request": request, + }, + partial=True, + ) + else: # PUT + serializer = ChallengeHostSerializer( + challenge_host, + data=request.data, + context={ + "challenge_host_team": challenge_host_team, + "request": request, + }, + ) + if serializer.is_valid(): + serializer.save() + response_data = serializer.data + return Response(response_data, status=status.HTTP_200_OK) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + @api_view(["POST"]) @throttle_classes([UserRateThrottle]) @permission_classes((permissions.IsAuthenticated, HasVerifiedEmail)) @authentication_classes((JWTAuthentication, ExpiringTokenAuthentication)) def create_challenge_host_team(request): - + """ + Create a challenge host team and add the requesting user as an admin. + """ serializer = ChallengeHostTeamSerializer( data=request.data, context={"request": request} ) @@ -240,20 +261,21 @@ def create_challenge_host_team(request): @authentication_classes((JWTAuthentication, ExpiringTokenAuthentication)) def remove_self_from_challenge_host_team(request, challenge_host_team_pk): """ - A user can remove himself from the challenge host team. + Allow a user to remove themselves from a challenge host team. """ try: ChallengeHostTeam.objects.get(pk=challenge_host_team_pk) except ChallengeHostTeam.DoesNotExist: response_data = {"error": "ChallengeHostTeam does not exist"} return Response(response_data, status=status.HTTP_406_NOT_ACCEPTABLE) + try: challenge_host = ChallengeHost.objects.filter( user=request.user.id, team_name__pk=challenge_host_team_pk ) challenge_host.delete() return Response(status=status.HTTP_204_NO_CONTENT) - except: # noqa E722 + except: # noqa: E722 response_data = {"error": "Sorry, you do not belong to this team."} return Response(response_data, status=status.HTTP_401_UNAUTHORIZED) @@ -263,7 +285,9 @@ def remove_self_from_challenge_host_team(request, challenge_host_team_pk): @permission_classes((permissions.IsAuthenticated, HasVerifiedEmail)) @authentication_classes((JWTAuthentication, ExpiringTokenAuthentication)) def invite_host_to_team(request, pk): - + """ + Invite a user to join a challenge host team. + """ try: challenge_host_team = ChallengeHostTeam.objects.get(pk=pk) except ChallengeHostTeam.DoesNotExist: