Я использую django-filter, который отлично работает, но у меня возникла проблема с фильтрацией раскрывающегося списка вариантов (основанного на модели) текущим пользователем. Это довольно простой и распространенный сценарий, когда у вас есть дочерняя таблица, которая имеет отношение «многие к одному» к родительской таблице. Я хочу отфильтровать таблицу дочерних записей, выбрав родителя. Это все довольно просто, стандартные вещи. Дегтярная ложка — это когда родительские записи создаются разными пользователями, и вы хотите показать в раскрывающемся списке только родительские записи, принадлежащие текущему пользователю.
Вот мой код из filter.py
import django_filters
from django import forms
from .models import Project, Task
from django_currentuser.middleware import get_current_user, get_current_authenticated_user
class MasterListFilter(django_filters.FilterSet):
project = django_filters.ModelChoiceFilter(
label='Projects',
name='project_fkey',
queryset=Project.objects.filter(deleted__isnull=True, user_fkey=3).distinct('code')
)
class Meta:
model = Task
fields = ['project']
@property
def qs(self):
parent = super(MasterListFilter, self).qs
user = get_current_user()
return parent.filter(master=True, deleted__isnull=True, user_fkey=user.id)
Этот бит работает нормально:
@property
def qs(self):
parent = super(MasterListFilter, self).qs
user = get_current_user()
return parent.filter(master=True, deleted__isnull=True, user_fkey=user.id)
Это фильтрует мой основной список, чтобы отображались только записи, для которых установлен главный флаг, которые не были удалены и принадлежат текущему пользователю. Это именно то, что я хочу.
Этот следующий бит также работает и дает мне отфильтрованный раскрывающийся список, который я ищу, потому что я жестко запрограммировал 3 как user.id
queryset=Project.objects.filter(deleted__isnull=True, user_fkey=3).distinct('code'),
Очевидно, я не хочу иметь жестко закодированный идентификатор. Мне нужно получить значение текущего пользователя. Следуя той же логике, которая используется для фильтрации основной таблицы, я получаю это.
class MasterListFilter(django_filters.FilterSet):
**user = get_current_user()**
project = django_filters.ModelChoiceFilter(
label='Projects',
name='project_fkey',
queryset=Project.objects.filter(deleted__isnull=True, user_fkey=**user.id**).distinct('code')
)
Однако это ненадежно, так как иногда показывает правильный список, а иногда нет. Например, если я вхожу в систему, и он не показывает список (т.е. он показывает только «---------»), а затем я перезапускаю свою службу apache2, она снова начинает работать, а затем в какой-то момент снова выпадает . Понятно, что это не долгосрочное решение.
Итак, как мне надежно получить текущего пользователя в моем filter.py, чтобы я мог использовать его для фильтрации моего раскрывающегося списка фильтров.
Заранее спасибо и удачного кодирования.
EDIT: Итак, следуя предложению Wiesion, я изменил свой код, как было предложено, но все еще получаю сообщение об ошибке None Type, говорящее, что у пользователя нет идентификатора атрибута. В основном кажется, что я не получаю текущего пользователя. Итак, вернувшись к документам и попытавшись объединить их предложение с Wiesion (чье объяснение имеет смысл - спасибо Wiesion), я пришел к следующему:
def Projects(request):
if request is None:
return Project.objects.none()
return lambda req: Project.objects.filter(deleted__isnull=True, user_fkey=req.user.id)
class MasterListFilter(django_filters.FilterSet):
project = django_filters.ModelChoiceFilter(
label='Projects',
name='project_fkey',
queryset=Projects
)
class Meta:
model = Task
fields = ['project']
Этот вид работает в теории, но ничего не дает мне в раскрывающемся списке, потому что
if request is None:
возвращает True и, следовательно, дает мне пустой список.
Итак... может ли кто-нибудь увидеть, где я ошибаюсь, что мешает мне получить доступ к запросу? Очевидно, что вторая часть кода работает на основе qs, который передается из моего представления, так что, может быть, мне нужно передать что-то еще? Мой код view.py ниже:
def masterlist(request, page='0'):
#Check to see if we have clicked a button inside the form
if request.method == 'POST':
return redirect ('tasks:tasklist')
else:
# Pre-filtering of user and Master = True etc is done in the MasterListFilter in filters.py
# Then we compile the list for Filtering by.
f = MasterListFilter(request.GET, queryset=Task.objects.all())
# Then we apply the complete list to the table, configure it and then render it.
mastertable = MasterTable(f.qs)
if int(page) > 0:
RequestConfig(request, paginate={'page': page, 'per_page': 10}).configure(mastertable)
else:
RequestConfig(request, paginate={'page': 1, 'per_page': 10}).configure(mastertable)
return render (request,'tasks/masterlist.html',{'mastertable': mastertable, 'filter': f})
Спасибо.