Как я могу реализовать глобальный, неявный фильтр в администраторе Django? - PullRequest
4 голосов
/ 17 марта 2011

У многих моих моделей есть внешний ключ для модели "Компания". Каждый вошедший в систему пользователь может быть частью одной или нескольких компаний (Пользователь m2m Company, не нуль).

Мне бы хотелось, чтобы у текущего пользователя-администратора были надеты «Очки компании», то есть список выбора, на странице индекса администратора или, возможно, в базовом заголовке, где они могут переключать свою «текущую» компанию. Для этого следует автоматически применить фильтр «Компания равна» - для моделей, имеющих внешний ключ к Компании, - в дополнение к любым другим фильтрам.

Какой лучший способ добиться этого?

NB. Это удобная функция для интерфейса администратора, на данном этапе защита моделей не требуется (это необходимо для клиентских представлений, но я могу просто использовать собственный менеджер и поиск через request.user).

Моя текущая идея:

  1. Сохранить текущую компанию в сеансе.

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

    a) список изменений: (? / &) "Company__eq = 42"

    b) change_view "add? Company = 42" для моделей, имеющих внешний ключ для Company.

    Для этого может потребоваться изменить или сопоставить шаблон URL-адреса, чтобы узнать их модель и проверить ее на наличие внешнего ключа (или я мог бы подготовить этот список заранее для повышения производительности).

  3. Включите в каждую форму ModelAdmin поле внешнего ключа, но скройте его с помощью CSS, чтобы в add_view ("new") добавлялось предустановленное значение внешнего ключа из ссылки без упоминания.

Считаете ли вы это приемлемым подходом?

Если бы http://code.djangoproject.com/ticket/10761 был реализован, я мог бы просто указать пользовательский набор запросов, который читает текущую компанию из request.session и покончить с этим. Может, лучше вместо этого ускорить (= создать и отправить патч) этот тикет?

РЕДАКТИРОВАТЬ: или, может быть, просто переопределить метод queryset () на каждом ModelAdmin, который нуждается в нем / имеет внешний ключ?

Ответы [ 2 ]

3 голосов
/ 17 марта 2011

Мой голос за переопределение ModelAdmin.queryset, так как у вас есть удобный доступ к запросу там.Переопределите save_model для пункта 3.

 class MyModelAdmin(admin.ModelAdmin):
    def queryset(self, request):
        qs = super(MyModelAdmin, self).queryset(request)
        if request.session.get('company_goggles'):
             return qs.filter(company=request.session['company_goggles'])
        return qs

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

class CompanyGogglesAdmin(admin.ModelAdmin):
    def queryset(self, request):
        qs = super(CompanyGoggleAdmin, self).queryset(request)
        if request.session.get('company_goggles'):
            return qs.filter(**{ getattr(self, 'company_field', 'company') : 
                          request.session['company_goggles'] })

Кстати, мне очень нравится эта терминология "очки компании".

1 голос
/ 17 марта 2011

Чтобы ответить на последний вопрос: если вы просто хотите отобразить определенные элементы набора запросов, вы можете переопределить метод ModelAdmin queryset() без проблем.Например, если вы установите компанию в текущем сеансе.Кроме того, вы можете переписать метод save_model(), чтобы company ForeignKey всегда указывал на компанию пользователя при сохранении формы:

class MyAdmin(admin.ModelAdmin):
    def queryset(self, request):
        company = request.session.get('company', None)
        qs = self.model._default_manager.get_query_set()
        if not company is None:
            qs = qs.filter(company=company)
        return qs

    def save_model(self, request, obj, form, change):
        company = request.session.get('company', None):
        instance = form.save(commit=False)
        if not change or not instance.company:
            instance.company = company
        instance.save()
        form.save_m2m()
        return instance
...