diff --git a/docs/images/final-version.png b/docs/images/final-version.png new file mode 100644 index 0000000..1ba58c3 Binary files /dev/null and b/docs/images/final-version.png differ 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