Reputation: 45
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.
Upvotes: 4
Views: 3802
Reputation: 477543
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'
]
Upvotes: 3