我正在使用基于类的视图,当我尝试将“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:\Users\xxxx\xxxx\xxxx\env\lib\site-packages\django\db\models\query.py, line 953, in _filter_or_exclude
Python Executable: C:\Users\xxxx\xxxx\xxxx\env\Scripts\python.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"]
如果需要,我可以添加更多信息
答案 0 :(得分:0)
创建 context['tasks'] 的深层副本并对对象的副本而不是主对象应用切片
答案 1 :(得分:0)
我做了一个变通方法,我将分页应用到上下文["tasks"],然后我做一个 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=1&{{ get_copy.urlencode }}">« first</a>
<a href="?page={{ task_page_obj.previous_page_number }}&{{ 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 }}&{{ get_copy.urlencode }}">next</a>
<a href="?page={{ task_page_obj.paginator.num_pages }}&{{ get_copy.urlencode }}">last »</a>
{% endif %}
</span>
</div>