Libro models.py

se le agrega related_name='categoria_libro' en el modelo libro

from pickletools import optimize
from django.db import models
from django.db.models.signals import post_save

#apps de tercero

from PIL import Image

from applications.autor.models import Autor

from .managers import LibroManager,CategoriaManager
# Create your models here.


class Categoria(models.Model):
    nombre = models.CharField(max_length=30)

    def __str__(self):
        return str(self.id) + ' - '+ self.nombre


class Libro(models.Model):
    categoria = models.ForeignKey(
        Categoria,
        on_delete=models.CASCADE,
        related_name='categoria_libro'    #sirve para que el modelo Categoria se conecte a Libro
    )
    autores = models.ManyToManyField(Autor)
    titulo = models.CharField(
        max_length=50
    )
    fecha = models.DateField('Fecha de Lanzamiento')
    portada = models.ImageField(upload_to='portada')
    visitas = models.PositiveIntegerField()
    stok=models.PositiveIntegerField(default=0)

    objects = LibroManager()

    class Meta:
        verbose_name='Libro'
        verbose_name_plural='Libros'
        ordering=['titulo','fecha']


    def __str__(self):
        return str(self.id) + '-'+ self.titulo

    def listar_libros_categoria(self,categoria):

        return self.filter(
            categoria__id=categoria
        ).order_by('titulo')

luego hacemos

python manage.py makemigrations
python manage.py migrate
python manage.py runserver

libro managers.py

class CategoriaManager(models.Manager):

    def categoria_por_autor(self, autor):

        return self.filter(
            #autores es un atributo del modelo Libro
            #categoria_libro__autores__nombre=autor
            #podria filtrarse por nombre,apellidos,nacionalidad,edad ya que estos 
            #son atributos del modelo Autor
            categoria_libro__autores__id=autor 
        ).distinct()    #sin repetirse

Conectamos el managager con el modelo y deberia quedar asi el models.py

from pickletools import optimize
from django.db import models
from django.db.models.signals import post_save

#apps de tercero

from PIL import Image

from applications.autor.models import Autor

from .managers import LibroManager,CategoriaManager
# Create your models here.


class Categoria(models.Model):
    nombre = models.CharField(max_length=30)

    objects=CategoriaManager()

    def __str__(self):
        return str(self.id) + ' - '+ self.nombre


class Libro(models.Model):
    categoria = models.ForeignKey(
        Categoria,
        on_delete=models.CASCADE,
        related_name='categoria_libro'
    )
    autores = models.ManyToManyField(Autor)
    titulo = models.CharField(
        max_length=50
    )
    fecha = models.DateField('Fecha de Lanzamiento')
    portada = models.ImageField(upload_to='portada')
    visitas = models.PositiveIntegerField()
    stok=models.PositiveIntegerField(default=0)

    objects = LibroManager()

    class Meta:
        verbose_name='Libro'
        verbose_name_plural='Libros'
        ordering=['titulo','fecha']


    def __str__(self):
        return str(self.id) + '-'+ self.titulo

    def listar_libros_categoria(self,categoria):

        return self.filter(
            categoria__id=categoria
        ).order_by('titulo')

COMPROBAR SI LA CONSULTA ESTA BIEN HECHA SIN CREAR UNA VISTA

SHELL DE DJANGO

en la terminal escribimos

python manage.py shell
from applications.libro.models import *
Categoria.objects.categoria_por_autor('4')