Невозможно получить связанные данные из поля ManyToManyField
Я пытаюсь получить связанные объекты из двух нижеприведенных моделей.
Следующие модели django с отношениями ManyToManyField.
Книга
class Book(models.Model):
authors = models.ManyToManyField(
to=Author, verbose_name="Authors", related_name="books_author"
)
bookshelves = models.ManyToManyField(
to=Bookshelf, verbose_name="Bookshelf", related_name="books_shelves"
)
copyright = models.NullBooleanField()
download_count = models.PositiveIntegerField(blank=True, null=True)
book_id = models.PositiveIntegerField(unique=True, null=True)
languages = models.ManyToManyField(
to=Language, verbose_name=_("Languages"), related_name="books_languages"
)
Автор
class Author(models.Model):
birth_year = models.SmallIntegerField(blank=True, null=True)
death_year = models.SmallIntegerField(blank=True, null=True)
name = models.CharField(max_length=128)
def __str__(self):
return self.name
class Meta:
verbose_name = _("Author")
verbose_name_plural = _("Author")
Мне нужно найти все Auhtors и связанные с ними книги. Я перепробовал множество различных способов, но ни один из них мне не помог.
Первый способ : использование prefetch_related
class AuthorListAPIView(APIErrorsMixin, generics.ListAPIView):
serializer_class = AuthorSerializer
queryset = Author.objects.exclude(name__isnull=True)
def get_queryset(self):
auths = queryset.prefetch_related(Prefetch("books_author"))
Второй способ с использованием родственного_имени 'books_auhtor'
class AuthorListAPIView(APIErrorsMixin, generics.ListAPIView):
serializer_class = AuthorSerializer
queryset = Author.objects.exclude(name__isnull=True)
def get_queryset(self):
auths = queryset.books_author.all()
Ни один из вышеперечисленных способов мне не помог. Я хочу подготовить список авторов и связанных с ними книг.
Например:-
[{'Author1':['Book1','Book2'],... }]
Префетчинг не является необходимым, но может быть использован для повышения эффективности, вы можете работать с:
class AuthorListAPIView(APIErrorsMixin, generics.ListAPIView):
serializer_class = AuthorWithBooksSerializer
queryset = Author.objects.exclude(name=None).prefetch_related('books_author')
В AuthorWithBooksSerializer
затем можно добавить данные книги, например:
from rest_framework import serializers
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = ('book_id', 'copyright')
class AuthorWithBooksSerializer(serializers.ModelSerializer):
books = BookSerializer(source='books_author', many=True)
class Meta:
model = Author
fields = ('name', 'books')
Здесь books
будет использовать BookSerializer
и таким образом кодировать список словарей.
Хотя вы можете использовать имя автора в качестве ключа объекта, я сильно не советую этого делать: это делает объект менее доступным, поскольку ключи больше не фиксированы, и если они содержат пробелы, это также может привести к большим проблемам с получением значения(й), связанного с данным именем атрибута.