Я использую django-фильтр, который работает отлично, но у меня возникла проблема с фильтрацией моего выпадающего списка вариантов (который основан на модели) текущим пользователем. Это довольно простой и распространенный сценарий, когда у вас есть дочерняя таблица, которая имеет отношение многие к одному с родительской таблицей. Я хочу отфильтровать таблицу дочерних записей, выбрав родителя. Это все довольно просто, стандартные вещи. Мазь для обкатки - это когда родительские записи создаются разными пользователями, и вы хотите показать только родительские записи в выпадающем списке, принадлежащем текущему пользователю.
Вот мой код от filters.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, я изменил свой код в соответствии с предложением, но все равно получаю сообщение об ошибке типа «Нет», говорящее, что у пользователя нет идентификатора атрибута. В общем, кажется, я не получаю текущего пользователя. Итак, возвращаясь к документам и пытаясь объединить их предложение с 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})
Спасибо.