Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Solution Politov #680

Open
wants to merge 15 commits into
base: master
Choose a base branch
from

Conversation

Alexandr-Politov
Copy link

No description provided.

Comment on lines +7 to +10
class ActorSerializer(serializers.Serializer):
id = serializers.IntegerField(read_only=True)
first_name = serializers.CharField(max_length=50)
last_name = serializers.CharField(max_length=50)

Choose a reason for hiding this comment

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

I'm not sure, but I think it is time to use serializers.ModelSerializer instead of Serializer
so your "serializers.py" code will become much shorter
4 strings almost for each class, except Movie with it ManyToMany realations

cinema/views.py Outdated
Comment on lines 18 to 21
class GenreList(views.APIView):
def get(self, request):
genres = Genre.objects.all()
serializer = GenreSerializer(genres, many=True)

Choose a reason for hiding this comment

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

I got a reject for not using parameter type annotations, including what the method returns

cinema/views.py Outdated
Comment on lines 58 to 61
class ActorList(
generics.GenericAPIView,
mixins.ListModelMixin,
mixins.CreateModelMixin

Choose a reason for hiding this comment

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

order is matter
mixins are going first

cinema/views.py Outdated
Comment on lines 73 to 76
class ActorDetail(
generics.GenericAPIView,
mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,

Choose a reason for hiding this comment

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

same here, just fix it everywhere

Copy link

@BastovOleksandr BastovOleksandr left a comment

Choose a reason for hiding this comment

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

I double checked, it seems like it's time to use serializers.ModelSerializer

Copy link

@Arsen-hrynevych Arsen-hrynevych left a comment

Choose a reason for hiding this comment

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

You've duplicated a lot of code that's already implemented in Django. To adhere to the DRY (Don't Repeat Yourself) principle, you could simplify your code.

Comment on lines 37 to 70
# class MovieSerializer(serializers.Serializer):
# id = serializers.IntegerField(read_only=True)
# title = serializers.CharField(max_length=255)
# description = serializers.CharField()
# duration = serializers.IntegerField()
# actors = serializers.PrimaryKeyRelatedField(
# many=True, queryset=Actor.objects.all()
# )
# genres = serializers.PrimaryKeyRelatedField(
# many=True, queryset=Genre.objects.all()
# )
#
# def create(self, validated_data):
# actors = validated_data.pop("actors")
# genres = validated_data.pop("genres")
# movie = Movie.objects.create(**validated_data)
# movie.actors.set(actors)
# movie.genres.set(genres)
# return movie
#
# def update(self, instance, validated_data):
# instance.title = validated_data.get("title", instance.title)
# instance.description = validated_data.get(
# "description", instance.description
# )
# instance.duration = validated_data.get("duration", instance.duration)
# if "actors" in validated_data:
# actors = validated_data.pop("actors")
# instance.actors.set(actors)
# if "genres" in validated_data:
# genres = validated_data.pop("genres")
# instance.genres.set(genres)
# instance.save()
# return instance

Choose a reason for hiding this comment

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

Commented-out code should not be included in the repository.

CinemaHallViewSet,
MovieViewSet,
)

Choose a reason for hiding this comment

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

2 blank lines after imports

Comment on lines +79 to +90

def get(self, request: Request, *args, **kwargs) -> Response:
return self.retrieve(request, *args, **kwargs)

def put(self, request: Request, *args, **kwargs) -> Response:
return self.update(request, *args, **kwargs)

def patch(self, request: Request, *args, **kwargs) -> Response:
return self.update(request, partial=True, *args, **kwargs)

def delete(self, request: Request, *args, **kwargs) -> Response:
return self.destroy(request, *args, **kwargs)

Choose a reason for hiding this comment

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

Mixins already take care of this for you, making the code redundant.

Copy link
Author

Choose a reason for hiding this comment

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

No. Mixins take care of this methods only with GenericViewSet. With GenericAPIView they only let you use this simplified srtucture.
image

Copy link

@MNDonut MNDonut Sep 30, 2024

Choose a reason for hiding this comment

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

@Alexandr-Politov actually for both generic classes you should use mixins(you are correct!). Mixins define actions (list, create, destroy,..) why Viewset and View have (get, post, delete,...) methods. But they aren't connected. By default DRF doesn't know that for "def post" it should call "create" action. This is why we need to do it explicitly.
Or we can inherit from ModelViewset/ListCreateAPIView/RetrieveUpdateDestroyView that already have connected methods with actions. The best idea it to view DRF code by opening these classes and check their implementation ;)

Comment on lines 7 to 34
class ActorSerializer(serializers.ModelSerializer):
class Meta:
model = Actor
fields = ("id", "first_name", "last_name")

def create(self, validated_data):
return Movie.objects.create(**validated_data)

def update(self, instance, validated_data):
instance.title = validated_data.get("title", instance.title)
instance.description = validated_data.get(
"description", instance.description
)
instance.duration = validated_data.get("duration", instance.duration)
class GenreSerializer(serializers.ModelSerializer):
class Meta:
model = Genre
fields = ("id", "name",)

instance.save()

return instance
class CinemaHallSerializer(serializers.ModelSerializer):
class Meta:
model = CinemaHall
fields = ("id", "name", "rows", "seats_in_row")


class MovieSerializer(serializers.ModelSerializer):
actors = serializers.PrimaryKeyRelatedField(
many=True, queryset=Actor.objects.all()
)
genres = serializers.PrimaryKeyRelatedField(
many=True, queryset=Genre.objects.all()
)

class Meta:
model = Movie
Copy link

Choose a reason for hiding this comment

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

We'll learn these serializers in API Serilizer topic, for this you should still use Serializer because
image

Comment on lines +11 to +12
)

Copy link

Choose a reason for hiding this comment

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

2 blank lines after the last import

Comment on lines +79 to +90

def get(self, request: Request, *args, **kwargs) -> Response:
return self.retrieve(request, *args, **kwargs)

def put(self, request: Request, *args, **kwargs) -> Response:
return self.update(request, *args, **kwargs)

def patch(self, request: Request, *args, **kwargs) -> Response:
return self.update(request, partial=True, *args, **kwargs)

def delete(self, request: Request, *args, **kwargs) -> Response:
return self.destroy(request, *args, **kwargs)
Copy link

@MNDonut MNDonut Sep 30, 2024

Choose a reason for hiding this comment

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

@Alexandr-Politov actually for both generic classes you should use mixins(you are correct!). Mixins define actions (list, create, destroy,..) why Viewset and View have (get, post, delete,...) methods. But they aren't connected. By default DRF doesn't know that for "def post" it should call "create" action. This is why we need to do it explicitly.
Or we can inherit from ModelViewset/ListCreateAPIView/RetrieveUpdateDestroyView that already have connected methods with actions. The best idea it to view DRF code by opening these classes and check their implementation ;)

serializer = GenreSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)

Choose a reason for hiding this comment

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

In this task it actually asks to

Don't forget return Response with errors if serializer is not valid:

Copy link

@Oleksl888 Oleksl888 left a comment

Choose a reason for hiding this comment

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

Good job!

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.

5 participants