Django запросов менеджера не работают в цепочке запросов. AttributeError: объект QuerySet не имеет атрибута - PullRequest
0 голосов
/ 21 июня 2020

Проблема: я реализовал настраиваемый менеджер для модели только с одним набором настраиваемых запросов с именем get_by_tag, и он работает нормально, если я использую его таким образом:

ViewStatistic.objects.get_by_tag('some-tag-name').filter(user=user_id)

Но когда я изменяю порядок запросов таким образом:

ViewStatistic.objects.filter(user=user_id).get_by_tag('some-tag-name')

не работает! и вызывает эту ошибку:

AttributeError: 'QuerySet' object has no attribute 'get_by_tag'

Я что-то упустил ?! Как это сделать в таком порядке?

PS: кастомный менеджер примерно такой:

class MyCustomManager(models.Manager):
    def get_by_tag(self, tag_name):
        posts = Post.objects.filter(tags__pk=tag_name)
        return super().get_queryset().filter(post__pk__in=posts)

Ответы [ 2 ]

1 голос
/ 21 июня 2020

Если вы хотите использовать свои методы набора запросов внутри цепочки запросов, а не только непосредственно после менеджера, вы должны определить их как методы настраиваемого класса QuerySet, который вы подключаете к менеджеру.

Описываются два решения в документации Django Создание менеджера с методами QuerySet .

Общая часть - настраиваемый класс QuerySet с методами набора запросов

class MyCustomQuerySet(models.QuerySet):
    def get_by_tag(self, tag_name):
        return self.filter(post__pk__in=Post.objects.filter(tags__pk=tag_name))

    # more possible queryset methods ...

A) , если у вашего менеджера есть только методы набора запросов и нет других настраиваемых методов тогда вы можете создать его просто из QuerySet.

class MyModel(models.Model):
    objects = MyCustomQuerySet.as_manager()

B) , если вашему менеджеру нужны также другие методы, которые не возвращают набор запросов:

class MyCustomManager(models.Manager):
    ...  # other methods

class MyModel(models.Model):
    objects = MyCustomManager.from_queryset(MyCustomQuerySet)()
0 голосов
/ 21 июня 2020

Когда вы говорите ViewStatistic.objects, он возвращает объект <django.db.models.manager.Manager>

В вашем случае, поскольку он имеет производный класс MyCustomManager, имеющий базовый класс models.manager, поэтому он возвращает объект <your_app.models.MyCustomManager>, который есть функция get_by_tag, и вы можете получить доступ к get_by_tag.

Для второго случая ViewStatistic.objects.filter return django.db.models.query.QuerySet объект и, конечно, у него нет метода с именем get_by_tag, поэтому вы получаете AttributeError.

Еще один момент, связанный с набором запросов: Результат уточнения QuerySet сам по себе является QuerySet , поэтому можно объединить уточнения в цепочку.

https://docs.djangoproject.com/en/3.0/topics/db/queries/#chaining - фильтры

В вашем случае get_by_tag return QuerySet, далее вы выполнили операцию .filter (), и это нормально. запрос для более подробной информации. https://docs.djangoproject.com/en/3.0/topics/db/queries/

...