Как я могу реализовать глобальный неявный фильтр в администраторе Django?

StackOverflow https://stackoverflow.com/questions/5344544

Вопрос

У многих моих моделей есть внешний ключ к модели «компании». Каждый зарегистрированный пользователь может быть частью одной или нескольких компаний (пользователь M2M Company, а не NULL).

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

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

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

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

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

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

    а) изменение_листа: (?/&) "Компания __eq = 42"

    б) изменение_view "Добавить? Компания = 42" для моделей, которые имеют иностранный ключ к компании.

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

  3. Включите в каждую модель, образуя поле внешнего ключа, но скрывайте его через CSS, чтобы change_view add («новый») включает в себя заданное значение внешнего ключа по ссылке, не упоминая его.

Вы считаете это жизнеспособным подходом?

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

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

Это было полезно?

Решение

Мой голос за перепродажи 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 и определите поле / по умолчанию, чтобы извлечь имя FieldName, а также предварительную автоматическую инъекцию компании.

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'] })

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

Другие советы

Чтобы ответить на последний вопрос: если вы просто хотите отобразить определенные элементы вашего запроса, вы можете переопределить ModelAdminS. 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
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top