Django — Meta.base_manager_name — сделать связанный аргумент в пользовательском наборе запросов и менеджере

У меня есть пользовательский менеджер моделей и пользовательский набор запросов, определенный специально для связанных объектов, что означает, что я определил Meta.base_manager_name в модели.

Я хотел бы использовать метод менеджера all(), который извлекает связанные объекты в OneToOneFeild.

Теперь я знаю, что это не имеет смысла, так как OneToOneFeild всегда будет возвращать один объект, нет необходимости в методе all(). Я работаю над проектом django-oscar и расширяю его модель «Партнер». Первоначально в нем было поле «пользователи» с ManyToManyField, а теперь оно изменено на OneToOneFeild.

Поле пользователей вызывается в коде несколько раз с использованием отношения user.partners.all(). Я не хочу расширять/изменять все эти места (я здесь ленивый?), так как я хочу, чтобы код был как можно более удобным для обновления, и поэтому вместо этого я хотел, чтобы менеджер моделей all() был определен, который будет работать. Не уверены, что это хорошая идея?

метод all() принимает пользовательский аргумент для возврата набора запросов экземпляра пользователя.

class PartnerQuerySet(models.QuerySet):
    def all(self, user):
        return self.filter(user=user)

class PartnerManager(models.Manager):

    def get_queryset(self):
        return PartnerQuerySet(self.model, using=self._db)

    def all(self, user):
        return self.get_queryset().all(users)

class Partner(models.Model):
    objects = PartnerManager()

    class Meta:
        base_manager_name = 'objects'

Проблема в том, что когда он используется со связанным объектом, он запрашивает пользовательский аргумент, что имеет смысл, но, поскольку я использую его со связанным объектом, я хотел использовать связанный объект в качестве аргумента, поэтому,

user.partner.all() - should use user as arg and fetch the results 

user.partner.all(user) - and I should not have to do the below

2 связанных вопроса: 1) Имеет ли это смысл - должен ли я это делать? 2) как я могу добиться user.partner.all() без добавления пользователя в arg

PS: я знаю, что могу работать с промежуточным программным обеспечением для get_current_user, но эта функция ненадежна, согласно некоторым ответам на другой вопрос на SO.


person Uma    schedule 14.08.2017    source источник


Ответы (1)


Я не думаю, что то, что вы пытаетесь сделать, сработает. Ваша новая ситуация с OneToOneField дает вам экземпляр партнера.

>>>> user.partner
<Partner xxx>

В то время как в старой ситуации с ManyToManyField было бы возвращено PartnerQuerySet.

>>>> user.partner
<PartnerQuerySet []>

Решением может быть создание собственного OneToOneField, но это, скорее всего, нарушит правило "простое лучше сложного" и, в конце концов, может даже потребовать больше работы, чем изменение всех существующих .all().

person White    schedule 14.08.2017