Подтвердить что ты не робот

Пользовательские менеджеры Django - как мне вернуть только объекты, созданные зарегистрированным пользователем?

Я хочу перезаписать диспетчер модели пользовательских объектов только для возврата объектов, созданных определенным пользователем. Пользователи-администраторы должны возвращать все объекты с помощью диспетчера модели объектов.

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

#### myproject/middleware/threadlocals.py

try:
    from threading import local
except ImportError:
    # Python 2.3 compatibility
    from django.utils._threading_local import local

_thread_locals = local()

def get_current_user():
    return getattr(_thread_locals, 'user', None)

class ThreadLocals(object):
    """Middleware that gets various objects from the
    request object and saves them in thread local storage."""
    def process_request(self, request):
        _thread_locals.user = getattr(request, 'user', None)

#### end

И в пользовательском менеджере вы можете вызвать метод get_current_user() для возврата только объектов, созданных определенным пользователем.

class UserContactManager(models.Manager):
    def get_query_set(self):
        return super(UserContactManager, self).get_query_set().filter(creator=get_current_user())

Это хороший подход к этому случаю? Будет ли это работать? Или это похоже на "использование кувалды, чтобы взломать орех"?; -)

Просто используя:

Contact.objects.filter(created_by= user)

в каждом представлении не выглядит очень аккуратно для меня.

EDIT Не используйте этот метод промежуточного программного обеспечения!!!

используйте подход, описанный Джеком М. ниже

Через некоторое время тестирование этого подхода показалось довольно странным, и при таком подходе вы смешиваете глобальное состояние с текущим запросом.

Используйте подход, представленный ниже. Это действительно легко и не нужно взламывать промежуточное ПО.

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

#in your models.py
class HourRecordManager(models.Manager):
    def for_user(self, user):
        return self.get_query_set().filter(created_by=user)

class HourRecord(models.Model):
    #Managers
    objects = HourRecordManager()

#in vour view you can call the manager like this and get returned only the objects from the currently logged-in user.

hr_set = HourRecord.objects.for_user(request.user)

См. также обсуждение относительно подхода на основе мультимедиа.

4b9b3361

Ответ 1

Один из способов справиться с этим - создать новый метод вместо переопределения get_query_set. Что-то вроде:

class UserContactManager(models.Manager):
    def for_user(self, user):
        return super(UserContactManager, self).get_query_set().filter(creator=user)

class UserContact(models.Model):
    [...]
    objects = UserContactManager()

Это позволяет вашему представлению выглядеть следующим образом:

contacts = Contact.objects.for_user(request.user)

Это должно помочь сохранить ваш взгляд простым, и потому, что вы будете использовать встроенные функции Django, он вряд ли ударит в будущем.

Ответ 2

Кажется необходимым использовать промежуточное программное обеспечение для хранения информации о пользователе.

Однако я бы предпочел не модифицировать ModelManager objects по умолчанию, но подключить его к другому менеджеру, который я буду использовать в коде, например, в вашем случае user_objects вместо объектов.

Поскольку вы будете использовать это только в представлениях @login_required, вам не нужна вся сложная обработка ошибок в Middleware.

Только мои 2 ¢.

Ответ 3

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

Ответ 4

Или даже проще и использовать внешний ключ для извлечения запроса.

Если у вас есть такая модель,

class HourRecord(models.Model):
    created_by = ForeignKey(get_user_model(), related_name='hour_records')

Вы можете запросить HourRecords в представлении пользователя с помощью простого:

request.user.hour_records.all()