Skip to content

Commit 01405d3

Browse files
committed
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.
1 parent 01b806f commit 01405d3

File tree

5 files changed

+67
-6
lines changed

5 files changed

+67
-6
lines changed

docs/index.md

+48-1
Original file line numberDiff line numberDiff line change
@@ -480,7 +480,7 @@ class AlbumSerializer(serializers.Serializer):
480480
2. With the fields `title`, `artist`, `release_year` with it respective fields
481481
3. We also need to list the fields inside the class Meta
482482

483-
Additionally we need to add 2 methods to let DRF know how to save and how to update the Albums.
483+
Additionally, we need to add 2 methods to let DRF know how to save and how to update the Albums.
484484

485485
The first is `create`
486486

@@ -518,6 +518,53 @@ Now we have 2 resources here, artists and albums
518518

519519
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.
520520

521+
## Building an API - Part III
522+
### Easy version
523+
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
524+
```python
525+
from django.urls import path, include
526+
from rest_framework import routers
527+
528+
from .views import ArtistViewSet, AlbumViewSet, SongViewSet
529+
530+
router = routers.DefaultRouter()
531+
router.register(r'artists', ArtistViewSet)
532+
router.register(r'albums', AlbumViewSet)
533+
# Add this new line below
534+
router.register(r'songs', SongViewSet)
535+
536+
urlpatterns = [
537+
path('', include(router.urls)),
538+
# path('', views.index, name='index'),
539+
]
540+
```
541+
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
542+
543+
```python
544+
from music.serializers import ArtistSerializer, AlbumSerializer, SongSerializer
545+
546+
class SongViewSet(viewsets.ModelViewSet):
547+
queryset = Song.objects.all()
548+
serializer_class = SongSerializer
549+
```
550+
551+
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.
552+
553+
```python
554+
from music.models import Artist, Album, Song
555+
556+
class SongSerializer(serializers.HyperlinkedModelSerializer):
557+
class Meta:
558+
model = Song
559+
fields = ['author', 'title', 'artist', 'album', 'duration']
560+
```
561+
562+
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. 🥳
563+
564+
![final-version.png](images/final-version.png)
565+
566+
Now you api is complete! Congratulations! 🍾🎉🎊
567+
521568
## Bonus content
522569

523570
### Serializers deep dive

first_api/music/models.py

+3
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,6 @@ class Song(models.Model):
2323
artist = models.ForeignKey(Artist, on_delete=models.CASCADE) # Artist or band name
2424
album = models.ForeignKey(Album, on_delete=models.CASCADE) # Album the song belongs to
2525
duration = models.IntegerField() # Duration of the song in seconds
26+
27+
def __str__(self):
28+
return f'{self.title} - {self.artist} - {self.album}'

first_api/music/serializers.py

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from rest_framework import serializers
22

3-
from music.models import Artist, Album
3+
from music.models import Artist, Album, Song
44

55

66
class ArtistSerializer(serializers.HyperlinkedModelSerializer):
@@ -35,3 +35,9 @@ def update(self, album, validated_data):
3535
album.save()
3636

3737
return album
38+
39+
40+
class SongSerializer(serializers.HyperlinkedModelSerializer):
41+
class Meta:
42+
model = Song
43+
fields = ['author', 'title', 'artist', 'album', 'duration']

first_api/music/urls.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
from django.urls import path, include
22
from rest_framework import routers
33

4-
from . import views
5-
from .views import ArtistViewSet, AlbumViewSet
4+
from .views import ArtistViewSet, AlbumViewSet, SongViewSet
65

76
router = routers.DefaultRouter()
87
router.register(r'artists', ArtistViewSet)
98
router.register(r'albums', AlbumViewSet)
9+
router.register(r'songs', SongViewSet)
1010

1111
urlpatterns = [
1212
path('', include(router.urls)),

first_api/music/views.py

+7-2
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
from rest_framework.generics import get_object_or_404
44
from rest_framework.response import Response
55

6-
from music.models import Artist, Album
7-
from music.serializers import ArtistSerializer, AlbumSerializer
6+
from music.models import Artist, Album, Song
7+
from music.serializers import ArtistSerializer, AlbumSerializer, SongSerializer
88

99

1010
def index(_request):
@@ -53,3 +53,8 @@ def destroy(self, request, pk=None):
5353
album = get_object_or_404(Album, pk=pk)
5454
album.delete()
5555
return Response(status=status.HTTP_204_NO_CONTENT)
56+
57+
58+
class SongViewSet(viewsets.ModelViewSet):
59+
queryset = Song.objects.all()
60+
serializer_class = SongSerializer

0 commit comments

Comments
 (0)