Как получить доступ к пользовательским методам QuerySet из менеджера внешнего ключа

Я использую Django Managers, чтобы создать API более высокого уровня для взаимодействия с мою базу данных и сделать мой код чище и читабельнее. Но в случае, если у меня отношение Foreignkey, я не могу использовать менеджер модели ForeignKey. Запросы более сложные, как показано ниже, но я просто упростил пример, чтобы его было легче читать и понять вопрос:

models.py:

class Community(models.Model):
    objects = CommunityManager()
    ...


class Inscription(models.Model):
    objects = InscriptionManager()

    ...
    community = models.ForeignKey("Community", related_name="inscriptions")
    created_at = models.DateTimeField()

managers.py:

from datetime import date
from django.db import models


class InscriptionQuerySet(models.query.QuerySet):
    def by_day(self, day=date.today()):
        return self.filter(created_at__day=day)

    ... # more queries


class InscriptionManager(models.Manager):
    def get_query_set(self):
        return InscriptionQuerySet(self.model, using=self._db)

    def today(self):
        return self.get_query_set().by_day()

    ... # more queries


class CommunityQuerySet(models.query.QuerySet):
    def by_type(self, type):
        return self.filter(type=type)

    ... # more queries


class CommunityManager(models.Manager):
    def get_query_set(self):
        return OrganistaionQuerySet(self.model, using=self._db)

    def by_type(self, type):
        return self.get_query_set().by_type(type)

    ... # more queries

Использование:

Inscription.objects.by_day() # return correctly all the inscriptions made today
Community.objects.by_type('type1') # return correctly all Communities that match

Проблема: но вот в чем проблема

community_b = Community.objects.get(id=12)
community_b.inscriptions.by_day() 
>>> AttributeError: 'ForeignRelatedObjectsDescriptor' object has no attribute 'by_day'

Как это исправить. Как настроить менеджер так, чтобы он учитывал взаимосвязь моделей.


person DhiaTN    schedule 17.12.2015    source источник
comment
Можете попробовать добавить use_for_related_fields = True к InscriptionManager? Проверьте это: docs.djangoproject.com/ ru/1.9/topics/db/managers/   -  person Rohit Jain    schedule 17.12.2015
comment
Почему у вас есть QuerySet и Manager для обеих моделей?   -  person Rohit Jain    schedule 17.12.2015
comment
@RohitJain Я пробовал это, но все та же ошибка. Да, он будет оптимизирован для одного менеджера, но сейчас просто для ясности я использую менеджер для каждой модели.   -  person DhiaTN    schedule 17.12.2015
comment
Все еще не уверен, почему у вас есть и менеджеры, и QuerySet, но можете ли вы переместить этот метод в QuerySet и назначить объекты в вашей модели InscriptionQuerySet.as_manager()? Я так думаю, должно работать. Меня устраивает.   -  person Rohit Jain    schedule 17.12.2015
comment
Я не понял, о каком методе вы говорите. Но так как это работает для вас. Думаю, будет полезно поделиться им в качестве ответа.   -  person DhiaTN    schedule 17.12.2015
comment
Я вижу, что ваш метод by_day() уже находится в InscriptionQuerySet, но вы пытаетесь получить к нему доступ в InscriptionManager. Как это работает? Что это за AnreiseQuerySet в методе вашего менеджера get_query_set()?   -  person Rohit Jain    schedule 17.12.2015
comment
ах ладно, я просто написал это неправильно, но это правильно сделано в моем коде. Я обновил пост. Как вы тестировали это и работает для вас, не могли бы вы поделиться им в качестве ответа?   -  person DhiaTN    schedule 17.12.2015


Ответы (1)


Я не вижу необходимости в Manager и QuerySet в вашем подходе. Вы могли бы просто покончить с QuerySet. Вот как я обычно реализую пользовательские менеджеры, и я попытался получить доступ к пользовательскому методу менеджера для обратной связи в одном из моих проектов, и он отлично работает:

class InscriptionQuerySet(models.QuerySet):
    def by_day(self, day=date.today()):
        return self.filter(created_at__day=day)

    def today(self):
        return self.by_day()

class CommunityQuerySet(models.QuerySet):
    def by_type(self, type):
        return self.filter(type=type)

А затем в своих моделях измените свой objects следующим образом:

class Community(models.Model):
    objects = CommunityQuerySet.as_manager()
    ...


class Inscription(models.Model):
    objects = InscriptionQuerySet.as_manager()

Я думаю, что вы сможете получить доступ к пользовательскому методу набора запросов с этой настройкой.

person Rohit Jain    schedule 17.12.2015
comment
Это очень хорошо работает для меня. Подход, который я использую, предлагается здесь в документация django, и я не знаю, в чем разница между этими двумя подходами. Но спасибо за Совет. - person DhiaTN; 17.12.2015