From 01405d38604ac10bda0ef1d84950a4e561c1adec Mon Sep 17 00:00:00 2001 From: FeliPython Date: Wed, 15 May 2024 10:18:14 -0400 Subject: [PATCH] Add Song resources to API and update documentation This commit adds a new resource, Song, to the current music API. Changes include registering the new SongViewSet to the router in urls.py, adding SongSerializer in serializers.py and updating the views in views.py. The getString method for Song model in models.py has also been updated. Additionally, the documentation (index.md) has been updated to reflect these changes. --- docs/index.md | 49 +++++++++++++++++++++++++++++++++- first_api/music/models.py | 3 +++ first_api/music/serializers.py | 8 +++++- first_api/music/urls.py | 4 +-- first_api/music/views.py | 9 +++++-- 5 files changed, 67 insertions(+), 6 deletions(-) diff --git a/docs/index.md b/docs/index.md index c2ad491..433e458 100644 --- a/docs/index.md +++ b/docs/index.md @@ -480,7 +480,7 @@ class AlbumSerializer(serializers.Serializer): 2. With the fields `title`, `artist`, `release_year` with it respective fields 3. We also need to list the fields inside the class Meta -Additionally we need to add 2 methods to let DRF know how to save and how to update the Albums. +Additionally, we need to add 2 methods to let DRF know how to save and how to update the Albums. The first is `create` @@ -518,6 +518,53 @@ Now we have 2 resources here, artists and albums I hope that at this time you understand the amount of shortcuts DRF gives you at the same time, if you want to customize it, it's still possible. +## Building an API - Part III +### Easy version +We are going to start from the urls one more time. We will add the route for the songs in our `music.urls` like in the snippet below +```python +from django.urls import path, include +from rest_framework import routers + +from .views import ArtistViewSet, AlbumViewSet, SongViewSet + +router = routers.DefaultRouter() +router.register(r'artists', ArtistViewSet) +router.register(r'albums', AlbumViewSet) +# Add this new line below +router.register(r'songs', SongViewSet) + +urlpatterns = [ + path('', include(router.urls)), + # path('', views.index, name='index'), +] +``` +After this we are going to create the `SongViewSet` in our `music.views` file using a `ModelViewSet` like in the snippet below. Also update Don't forget to add the import for the `SongSerializer` in your imports + +```python +from music.serializers import ArtistSerializer, AlbumSerializer, SongSerializer + +class SongViewSet(viewsets.ModelViewSet): + queryset = Song.objects.all() + serializer_class = SongSerializer +``` + +At this point the `SongSerializer` doesn't exist yet, so now we are going to create it. Here also update the imports for the models including the `Song` model. Here there is a snippet so you see the changes you have to do on you `music.serializers` file. + +```python +from music.models import Artist, Album, Song + +class SongSerializer(serializers.HyperlinkedModelSerializer): + class Meta: + model = Song + fields = ['author', 'title', 'artist', 'album', 'duration'] +``` + +With this part done you will be able to run you application and see something like this on you api with all 3 resource working in your API, Artist, Album and Song. πŸ₯³ + +![final-version.png](images/final-version.png) + +Now you api is complete! Congratulations! πŸΎπŸŽ‰πŸŽŠ + ## Bonus content ### Serializers deep dive diff --git a/first_api/music/models.py b/first_api/music/models.py index 03b7f4c..51866eb 100644 --- a/first_api/music/models.py +++ b/first_api/music/models.py @@ -23,3 +23,6 @@ class Song(models.Model): artist = models.ForeignKey(Artist, on_delete=models.CASCADE) # Artist or band name album = models.ForeignKey(Album, on_delete=models.CASCADE) # Album the song belongs to duration = models.IntegerField() # Duration of the song in seconds + + def __str__(self): + return f'{self.title} - {self.artist} - {self.album}' diff --git a/first_api/music/serializers.py b/first_api/music/serializers.py index 2097b33..961d0ed 100644 --- a/first_api/music/serializers.py +++ b/first_api/music/serializers.py @@ -1,6 +1,6 @@ from rest_framework import serializers -from music.models import Artist, Album +from music.models import Artist, Album, Song class ArtistSerializer(serializers.HyperlinkedModelSerializer): @@ -35,3 +35,9 @@ def update(self, album, validated_data): album.save() return album + + +class SongSerializer(serializers.HyperlinkedModelSerializer): + class Meta: + model = Song + fields = ['author', 'title', 'artist', 'album', 'duration'] diff --git a/first_api/music/urls.py b/first_api/music/urls.py index 19b51ad..666792d 100644 --- a/first_api/music/urls.py +++ b/first_api/music/urls.py @@ -1,12 +1,12 @@ from django.urls import path, include from rest_framework import routers -from . import views -from .views import ArtistViewSet, AlbumViewSet +from .views import ArtistViewSet, AlbumViewSet, SongViewSet router = routers.DefaultRouter() router.register(r'artists', ArtistViewSet) router.register(r'albums', AlbumViewSet) +router.register(r'songs', SongViewSet) urlpatterns = [ path('', include(router.urls)), diff --git a/first_api/music/views.py b/first_api/music/views.py index 616e46f..88b5acd 100644 --- a/first_api/music/views.py +++ b/first_api/music/views.py @@ -3,8 +3,8 @@ from rest_framework.generics import get_object_or_404 from rest_framework.response import Response -from music.models import Artist, Album -from music.serializers import ArtistSerializer, AlbumSerializer +from music.models import Artist, Album, Song +from music.serializers import ArtistSerializer, AlbumSerializer, SongSerializer def index(_request): @@ -53,3 +53,8 @@ def destroy(self, request, pk=None): album = get_object_or_404(Album, pk=pk) album.delete() return Response(status=status.HTTP_204_NO_CONTENT) + + +class SongViewSet(viewsets.ModelViewSet): + queryset = Song.objects.all() + serializer_class = SongSerializer