Django - 获取切片后无法过滤查询

时间:2021-05-29 00:32:46

标签: 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:\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"]

如果需要,我可以添加更多信息

2 个答案:

答案 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 }}">&laquo; 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 &raquo;</a>
    {% endif %}
</span>
</div>
相关问题