如何在 Django 中获取同一作者的书籍

How to get books of the the same author in Django

我正在开发一个在线书店。 这是模型:

class Author(models.Model):
    name = models.CharField(max_length=250, unique=True)

class Publisher(models.Model):
    name = models.CharField(max_length=250, unique=True)
    
class Book(models.Model):
    author = models.ManyToManyField(Author, related_name='authors')
    publisher = models.ForeignKey(Publisher, on_delete=models.PROTECT, blank=True, null=True)   
    isbn13 = models.BigIntegerField(unique=True)
    name = models.CharField(max_length=500)
    ... 

视图如下:

class AuthorsListView(ListView):
    model = Author
    context_object_name = 'authors_list'
    template_name = 'authors_list.html'
    paginate_by = 500

class AuthorBooksListView(ListView):
    model = Book
    context_object_name = 'author_books'
    template_name = 'author_books.html'

    def get_queryset(self, **kwargs):
        author_id = Author.objects.get(pk = self.kwargs['pk'])
        qs = super().get_queryset(**kwargs)
        return qs.filter(author = author_id)


    def get_context_data(self, **kwargs):
        # Call the base implementation first to get a context
        context = super().get_context_data(**kwargs)
        # Add in a QuerySet 
        context['author'] = Author.objects.get(pk = self.kwargs['pk'])
        return context

class PublishersListView(ListView):
    model = Publisher
    context_object_name = 'publishers_list'
    template_name = 'publishers_list.html'
    paginate_by = 500

class PublisherBooksListView(ListView):
    model = Book
    context_object_name = 'publisher_books'
    template_name = 'publisher_books.html'
    paginate_by = 20

    def get_queryset(self, **kwargs):
        publisher_id = Publisher.objects.get(pk = self.kwargs['pk'])
        qs = super().get_queryset(**kwargs)
        return qs.filter(publisher = publisher_id)

    def get_context_data(self, **kwargs):
        # Call the base implementation first to get a context
        context = super().get_context_data(**kwargs)
        # Add in a QuerySet 
        context['publisher'] = Publisher.objects.get(pk = self.kwargs['pk'])
        return context

class BooksListView(ListView):
    model = Book
    context_object_name = 'books_list'
    template_name = 'books_list.html'
    paginate_by = 100


class BookDetailView(DetailView):
    model = Book
    template_name = 'book_detail.html'

这是网址:

    path('authors/', AuthorsListView.as_view(), name = 'authors_list'),
    path('author/<int:pk>/', AuthorBooksListView.as_view(), name='author_detail'),
    path('publishers/', PublishersListView.as_view(), name='publishers_list'),
    path('publisher/<int:pk>/', PublisherBooksListView.as_view(), name='publisher_detail'),
    path('', BooksListView.as_view(), name='books_list'),
    path('book/<int:pk>/', BookDetailView.as_view(), name='book_detail'),

在我要显示的图书详情页面上:

  1. 同一作者的相关书籍
  2. 同一出版商的相关书籍 我怎样才能做到这一点?请帮助我。

我试图将这些代码添加到 BookDetailView:

    def get_queryset(self, **kwargs):
        book = Book.objects.get(pk = self.kwargs['pk'])
        queryset = {
            'books': Book.objects.all(),
            'publisher_books': Book.objects.filter(publisher = book.publisher.id),
        }
            
        return queryset

但是它给我一个错误:

'dict' object has no attribute 'filter'

@djangodjarhes - 你能试试下面的方法吗?理想情况下,如果我想更改除 URL kwargs 之外的查询集过滤方式,我会修改 get_queryset。对于其他任何事情,我覆盖 get_context_data

  def get_context_data(self, **kwargs):
        context = super(BookDetailView, self).get_context_data(**kwargs)
        book =  Book.objects.get(pk = self.kwargs['pk'])
        publisher_books = Book.objects.filter(publisher = book.publisher.id)
        context["publisher_books"] = publisher_books
        return context

关于你的情况,欢迎随时指正

 queryset = {
                'books': Book.objects.all(),
                'publisher_books': Book.objects.filter(publisher = book.publisher.id),
        }

这是不对的。当 get_queryset 应该 return 一个查询集时,你正在 returning 一个字典。你不能 return 听写。要么你改变它来做到这一点

queryset = Book.objects.filter(publisher = book.publisher.id)
return queryset

如果你想 return 字典,请使用 get_context_data。