4

in my models i have Book and Author with M2M relationship.

models.py

from django.db import models


from django.db import models


class Book(models.Model):
    title          = models.CharField(max_length=200)
    published_date = models.DateField(auto_now_add=False)
    categories     = models.CharField(max_length=300, null=True, blank=True)
    average_rating = models.FloatField(null=True, blank=True)
    ratings_count  = models.IntegerField(null=True, blank=True)
    thumbnail      = models.URLField(null=True, blank=True)

def authors(self):
    return self.author_set.all()

def __str__(self):
    return f'title: {self.title} \n' \
           f'date of publication: {self.published_date}'


class Author(models.Model):
    name  = models.CharField(max_length=200)
    books = models.ManyToManyField(Book)

    def __str__(self):
        return str(self.name)

in my serializer i'm getting authors from def authors in models.py

serializers.py
    class Meta:
        model = Author
        fields = ['name']


class BookSerializer(serializers.ModelSerializer):
    authors = AuthorSerializer(many=True)

    class Meta:
        model = Book
        fields = [
            'authors',
            'title',
            'published_date',
            'categories',
            'average_rating',
            'ratings_count',
            'thumbnail'
        ]

so in views.py i want to filter books by authors

views.py
class BooksListAPIView(generics.ListAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    filter_backends = (filters.OrderingFilter, DjangoFilterBackend)
    filter_fields = ['published_date', 'authors']
    ordering_fields = ['published_date']

but it gives me this error

'Meta.fields' must not contain non-model field names: authors 

any idea how can i filter data with authors so i can extract books of given authors. I would like to have a choice of selecting filters. Thanks in advance.

1 Answer 1

3

You remove the authors from the fields, and let this be handled by the AuthorSerializer in the serializer:

class BookSerializer(serializers.ModelSerializer):
    authors = AuthorSerializer(source='author_set', many=True)

    class Meta:
        model = Book
        fields = [  # ← no authors
            'author_set',
            'title',
            'published_date',
            'categories',
            'average_rating',
            'ratings_count',
            'thumbnail'
        ]

Note that you can rename the relation in reverse with the related_name=… parameter:

class Author(models.Model):
    name  = models.CharField(max_length=200)
    books = models.ManyToManyField(Book, related_name='authors')

    def __str__(self):
        return self.name

in that case, the source is simply authors:

class BookSerializer(serializers.ModelSerializer):
    #                   no source ↓
    authors = AuthorSerializer(many=True)

    class Meta:
        model = Book
        fields = [
            'authors',
            'title',
            'published_date',
            'categories',
            'average_rating',
            'ratings_count',
            'thumbnail'
        ]
Sign up to request clarification or add additional context in comments.

10 Comments

it gives me this error:The field 'authors' was declared on serializer BookSerializer, but has not been included in the 'fields' option.
@dawid: but did you set the source to author_set?
Yes i did and i removed def authors from model and removed authors from fields in Bookserializer
Should i leave this def authors method in models.py?
@dawid: did you set the related_name to authors?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.