Подзапрос отношения многие ко многим в Django 1.9 - PullRequest
0 голосов
/ 20 марта 2019

У меня есть такие модели:

class Genre(models.Model):
    name = models.TextField(null=True, blank=True)
    min_age = models.IntegerField(default=0)
    max_age = models.IntegerField(default=0)
    objects = GenreManager()

    class Meta:
        get_latest_by = 'id'


class Book(models.Model):
    name = models.TextField(null=True, blank=True)
    genres = models.ManyToManyField(Genre, related_name='genres')
    suggested_age = models.IntegerField(default=0)
    objects = BookManager()

, и я хочу запросить его таким образом: могут быть дубликаты (при изменении минимального / максимального возраста новый объект будет сохранен в дБ), но яЯ хочу получить последнюю версию, поэтому я придумываю:

class GenreManager(models.Manager):
    def get_latest_genre_obj(self, genre):
        return self.get_queryset().filter(name=genre).latest()

, чтобы иметь возможность ее получить.Теперь я хочу получить книги, используя Genre объект сверху - мне нужны минимальные и максимальные значения возраста в моем запросе.Я пробовал что-то вроде этого:

class BookManager(models.Manager):
    def get_books_from_genre(self, genre):
        genre = Genre.objects.get_latest_genre_obj(genre)
        return self.get_queryset().annotate(actual_genre=genre).filter(actual_genre__min_age__gte=F('suggested_age'), actual_genre__max_age__lte=F('suggested_age'))

Но похоже, что я не могу аннотировать объект другим объектом:

AttributeError: 'Genre' object has no attribute 'resolve_expression'

Итак, как запросить его, как я хочу?Я думал о Subquery(), так как думал, что он может мне помочь, но это функция Django 1.11, и я использую версию 1.9.Подводя итог, что я хочу достичь: из жанров, получить новейший (с самым высоким id) объект с определенным именем и использовать его поля при запросе книг - поэтому мне нужно иметь доступ к его полям.

1 Ответ

0 голосов
/ 20 марта 2019

Я думаю, вам нужно удалить annotate из кода и использовать его следующим образом:

Если вы хотите Книги для определенного жанра:

class BookManager(models.Manager):
    def get_books_from_genre(self, genre):
        genre_object = Genre.objects.get_latest_genre_obj(genre)
        return self.get_queryset().filter(genres=genre_object)

Теперь, если вы хотите иметь книги из разных жанров с одинаковыми именами, вы можете попробовать это так:

class BookManager(models.Manager):
    def get_books_from_genre(self, genre):
        return self.get_queryset().filter(genres__name=genre, genres__min_age__gte=F('suggested_age'), genres__max_age__lte=F('suggested_age'))
...