#python #django #django-views
Вопрос:
Я использую представления на основе классов, и когда я пытаюсь использовать «paginate_by = 6» с «def get_context_data(self, **kwargs):», я получаю следующую ошибку:
AssertionError at /
Cannot filter a query once a slice has been taken.
Request Method: GET
Request URL: http://127.0.0.1:8000/
Django Version: 3.2
Exception Type: AssertionError
Exception Value:
Cannot filter a query once a slice has been taken.
Exception Location: C:Usersxxxxxxxxxxxxenvlibsite-packagesdjangodbmodelsquery.py, line 953, in _filter_or_exclude
Python Executable: C:UsersxxxxxxxxxxxxenvScriptspython.exe
Python Version: 3.9.1
Python Path:
['C:\Users\xxxx\xxxx\xxxx',
'C:\Program Files\Python39\python39.zip',
'C:\Program Files\Python39\DLLs',
'C:\Program Files\Python39\lib',
'C:\Program Files\Python39',
'C:\Users\xxxx\xxxx\xxxx\env',
'C:\Users\xxxx\xxxx\xxxx\env\lib\site-packages']
Server time: Sat, 29 May 2021 00:11:20 0000
Я пытаюсь выполнить разбиение на страницы для результата фильтров, например, если фильтры не применены, он должен выполнить разбиение на страницы для всех задач.
Я нашел только решение, которое не использует функции с помощью пагинатора. Я хотел бы знать, возможно ли это сделать с представлением на основе классов и как, я немного потерялся в этом.
мой views.py:
class TaskList(LoginRequiredMixin, ListView):
model = Task
context_object_name = "tasks"
template_name = "todo/tasks.html"
paginate_by = 6
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["tasks"] = context["tasks"].filter(user=self.request.user)
context["count"] = context["tasks"].filter(complete=False).count()
context["projects"] = Project.objects.all()
search_input = self.request.GET.get("search") or ""
project_input = self.request.GET.get("project") or ""
complete_input = self.request.GET.get("complete") or ""
if search_input:
context["tasks"] = context["tasks"].filter(title__icontains=search_input)
context["count"] = context["tasks"].filter(complete=False).count()
context["search_input"] = search_input
if project_input:
context["project_selected"] = project_input
context["tasks"] = context["tasks"].filter(
project__name__icontains=project_input
)
context["count"] = context["tasks"].filter(complete=False).count()
if complete_input == "all":
context["complete_selected"] = complete_input
context["tasks"] = context["tasks"].filter(user=self.request.user)
context["count"] = context["tasks"].filter(complete=False).count()
else:
if complete_input:
context["complete_selected"] = complete_input
context["tasks"] = context["tasks"].filter(
user=self.request.user, complete=True
)
context["count"] = context["tasks"].filter(complete=True).count()
else:
context["complete_selected"] = ""
context["tasks"] = context["tasks"].filter(
user=self.request.user, complete=False
)
return context
мой models.py:
class Task(models.Model):
project = models.ForeignKey(Project, on_delete=CASCADE)
user = models.ForeignKey(User, on_delete=SET_NULL, null=True, blank=True)
title = models.CharField(max_length=255)
description = RichTextField(null=True, blank=True)
complete = models.BooleanField(default=False)
time = models.TimeField(default=datetime.time(00, 00))
date = models.DateField(default=datetime.date.today)
def __str__(self):
return self.title
class Meta:
ordering = ["complete", "-date", "title"]
при необходимости я могу добавить дополнительную информацию
Ответ №1:
создайте глубокую копию контекста [«задачи»] и примените нарезку к копии объекта вместо основного объекта
Комментарии:
1. Не могли бы вы привести мне пример того, как это должно быть сделано?
Ответ №2:
Я сделал обходной путь, где я применяю разбиение на страницы к контексту[«задачи»], а затем делаю копию URL-адреса, чтобы поддерживать фильтрацию на каждой странице.
views.py:
class TaskList(LoginRequiredMixin, ListView):
model = Task
context_object_name = "tasks"
template_name = "myapp/list.html"
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["tasks"] = context["tasks"].filter(user=self.request.user)
context["count"] = context["tasks"].filter(complete=False).count()
context["projects"] = Project.objects.all()
search_input = self.request.GET.get("search") or ""
project_input = self.request.GET.get("project") or ""
complete_input = self.request.GET.get("complete") or ""
if search_input:
context["tasks"] = context["tasks"].filter(title__icontains=search_input)
context["count"] = context["tasks"].filter(complete=False).count()
context["search_input"] = search_input
if project_input:
context["project_selected"] = project_input
context["tasks"] = context["tasks"].filter(
project__name__icontains=project_input
)
context["count"] = context["tasks"].filter(complete=False).count()
if complete_input == "all":
context["complete_selected"] = complete_input
context["tasks"] = context["tasks"].filter(user=self.request.user)
context["count"] = context["tasks"].filter(complete=False).count()
else:
if complete_input:
context["complete_selected"] = complete_input
context["tasks"] = context["tasks"].filter(
user=self.request.user, complete=True
)
context["count"] = context["tasks"].filter(complete=True).count()
else:
context["complete_selected"] = ""
context["tasks"] = context["tasks"].filter(
user=self.request.user, complete=False
)
# Pagination
paginated_tasks = Paginator(context["tasks"], 6)
page_number = self.request.GET.get("page")
task_page_obj = paginated_tasks.get_page(page_number)
context["task_page_obj"] = task_page_obj
get_copy = self.request.GET.copy()
if get_copy.get("page"):
get_copy.pop("page")
context["get_copy"] = get_copy
return context
list.html:
...
{% for task in task_page_obj %}
{% empty %}
<p>No tasks to show...</p>
{% endfor %}
<div class="pagination">
<span class="step-links">
{% if task_page_obj.has_previous %}
<a href="?page=1amp;{{ get_copy.urlencode }}">amp;laquo; first</a>
<a href="?page={{ task_page_obj.previous_page_number }}amp;{{ get_copy.urlencode }}">previous</a>
{% endif %}
<span class="current">
Page {{ task_page_obj.number }} of {{ task_page_obj.paginator.num_pages }}.
</span>
{% if task_page_obj.has_next %}
<a href="?page={{ task_page_obj.next_page_number }}amp;{{ get_copy.urlencode }}">next</a>
<a href="?page={{ task_page_obj.paginator.num_pages }}amp;{{ get_copy.urlencode }}">last amp;raquo;</a>
{% endif %}
</span>
</div>
Ответ №3:
В этом случае вы должны отфильтровать свой набор запросов в функции ниже, и он переопределит набор запросов по умолчанию:
def get_queryset(self): return '<your query>'
ошибка возникает из-за того, что вы пытаетесь изменить не оцененный набор запросов после его фильтрации. и теперь вы можете использовать paginate_by = n
, вы не должны получать никаких ошибок.