0

I have two models in a 'many to many' relationship Video and Genre. I want to represent them in my API using the Django Rest Framework and with Hyperlinking. I have tried using the the nested relationships solution that I have found over the internet but it brings me an error for the list viewss eg genres/ and videos/ as described below.

models.py

class VideoGenre(models.Model):
    video = models.ForeignKey(Video, on_delete=models.CASCADE, related_name='genres')
    genres = models.ForeignKey(Genre, on_delete=models.CASCADE, related_name='videos')

    class Meta:
        unique_together = ['video', 'genre']

class Video(models.Model):
    genres = models.ManyToManyField(Genre, related_name="videos", blank=True, through='VideoGenre')
    title = serializers.CharField(default=serializers.CurrentUserDefault())

class Genre(models.Model):
name = models.CharField(max_length=20)
descr = models.CharField(max_length=255)

serializers.py

class GenreSerializer(serializers.HyperlinkedModelSerializer):

    videos = serializers.HyperlinkedIdentityField(many=True, view_name="video-detail")

    class Meta:
        model = ku_api_models.Genre
        fields = "__all__"

class VideoSerializer(serializers.HyperlinkedModelSerializer):
    genres = GenreSerializer(source='genre_set', many=True, read_only=True)

    class Meta:
        model = ku_api_models.Video
        fields = "__all__"

class VideoGenreSerializer(serializers.HyperlinkedModelSerializer):
    video = serializers.ReadOnlyField(source='video.id')
    genre = serializers.ReadOnlyField(source='genre.id')

    class Meta:
        model = ku_api_models.VideoGenre
        fields = "__all__"
        unique_together = ['video', 'genre']

views.py

class VideoDetailView(RetrieveUpdateDestroyAPIView):
    parser_classes = (MultiPartParser,)
    serializer_class = VideoSerializer
    queryset = Video.objects.all()

    def perform_update(self, serializer):
        serializer.save(owner=self.request.user)

class VideoListView(ListCreateAPIView):
    parser_classes = (MultiPartParser,)
    serializer_class = VideoSerializer
    queryset = Video.objects.all()

    def perform_create(self, serializer):
        serializer.save(owner=self.request.user)

class GenreListView(ListCreateAPIView):
    serializer_class = GenreSerializer
    queryset = Genre.objects.all()

class GenreDetailtView(RetrieveUpdateDestroyAPIView):
    serializer_class = GenreSerializer
    queryset = Genre.objects.all()

urls.py

path('videos/', views.VideoListView.as_view(), name='video-list'),
path('videos/<int:pk>', views.VideoDetailView.as_view(), name='video-detail'),
path('genres/', views.GenreListView.as_view(), name="genre-list"),
path('genres/<int:pk>', views.GenreDetailtView.as_view(), name="genre-detail"),

I am getting below exception on the browsable API renderer

Exception Type: ProgrammingError at /api/genres/ Exception Value: relation "ku_api_videogenre" does not exist LINE 1: ..._video"."owner_id" FROM "ku_api_video" INNER JOIN "ku_api_vi...

I have looked into these below links as referred above django rest framework serializing many to many field

many to many relationship through an intermidiate model

serializing many to many field

... and tried them but getting the same/almost the same, only different is the relation name that "does not exist"

What am I missing? How to make it right? Thanks

mnekx
  • 18
  • 4

1 Answers1

0

I have found a way to this: Changes will be in the serializers.py

serializers.py

class VideoSerializer(serializers.HyperlinkedModelSerializer):
    genres = serializers.HyperlinkedRelatedField(many=True, read_only=False, view_name='genre-detail', queryset=ku_api_models.Genre.objects.all())


    class Meta:
        model = ku_api_models.Video
        #fields = ('url', 'id', 'datetime_added', 'title', 'video_file', 'owner')
        fields = "__all__"

    def create(self, validated_data):
        genres = validated_data.pop('genres', [])
        video_instance = ku_api_models.Video.objects.create(**validated_data)
        video_instance.genres.set(genres)
        return video_instance

    def update(self, instance, validated_data):
        genres = validated_data.pop('genres', [])
        instance.genres.set(genres)
        instance.save()
        return instance

class VideoGenreSerializer(serializers.HyperlinkedModelSerializer):

    class Meta:
        model = ku_api_models.VideoGenre
        fields = "__all__"

class GenreSerializer(serializers.HyperlinkedModelSerializer):

    class Meta:
        model = ku_api_models.Genre
        fields = "__all__"

Source: Docs: intermediary-manytomany

mnekx
  • 18
  • 4