-
Notifications
You must be signed in to change notification settings - Fork 722
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
base: master
Are you sure you want to change the base?
Solution Politov #680
Conversation
class ActorSerializer(serializers.Serializer): | ||
id = serializers.IntegerField(read_only=True) | ||
first_name = serializers.CharField(max_length=50) | ||
last_name = serializers.CharField(max_length=50) |
There was a problem hiding this comment.
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
class GenreList(views.APIView): | ||
def get(self, request): | ||
genres = Genre.objects.all() | ||
serializer = GenreSerializer(genres, many=True) |
There was a problem hiding this comment.
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
class ActorList( | ||
generics.GenericAPIView, | ||
mixins.ListModelMixin, | ||
mixins.CreateModelMixin |
There was a problem hiding this comment.
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
class ActorDetail( | ||
generics.GenericAPIView, | ||
mixins.RetrieveModelMixin, | ||
mixins.UpdateModelMixin, |
There was a problem hiding this comment.
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
There was a problem hiding this 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
There was a problem hiding this 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.
cinema/serializers.py
Outdated
# 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 |
There was a problem hiding this comment.
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, | ||
) | ||
|
There was a problem hiding this comment.
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
|
||
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) |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
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 ;)
cinema/serializers.py
Outdated
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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
) | ||
|
There was a problem hiding this comment.
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
|
||
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) |
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good job!
No description provided.