【问题标题】:Django Adding Pagination To Search Form PageDjango将分页添加到搜索表单页面
【发布时间】:2023-03-12 08:23:01
【问题描述】:

如何向此表单的搜索功能添加分页功能?

默认情况下,在页面刷新时,循环的 HTML 模板会显示所有课程的所有结果。当用户在表单中输入条件时,表单会根据用户输入的内容过滤课程结果模板以进行循环。页面刷新有没有办法在页面上只显示设置的课程结果限制而不是全部?然后,当用户搜索/过滤时,页面上 X 个课程结果的分页限制仍需要显示,但仍适用于搜索条件/过滤器。

  • HTML:
    <form id='courseform' action="." method="get">
    <div class="form-row">
        <div class="form-group col-12"> {{ form.title__icontains }} </div>
        <div class="form-group col-md-2 col-lg-2"> {{ form.visited_times__gte.label_tag }} {{ form.visited_times__gte }} </div>
        <div class="form-group col-md-2 col-lg-2"> {{ form.visited_times__lte.label_tag }} {{ form.visited_times__lte }} </div>
        <div class="form-group col-md-2 col-lg-2"> {{ form.created_at__gte.label_tag }} {{ form.created_at__gte }} </div>
        <div class="form-group col-md-2 col-lg-2"> {{ form.created_at__lte.label_tag }} {{ form.created_at__lte }} </div>
        <div class="form-group col-md-2"> {{ form.skill_level.label_tag }} {{ form.skill_level }} </div>
        <div class="form-group col-md-2"> {{ form.subjects.label_tag }} {{ form.subjects }} </div>
    </div>

        <script src='https://www.google.com/recaptcha/api.js?render=6LeHe74UAAAAAKRm-ERR_fi2-5Vik-uaynfXzg8N'></script>
        <div class="g-recaptcha" data-sitekey="6LeHe74UAAAAAKRm-ERR_fi2-5Vik-uaynfXzg8N"></div>
        <button type="submit" class="btn btn-primary form-control">Search</button>
    <p>This site is protected by reCAPTCHA and the Google
        <a target="_blank" rel="noopener noreferrer" href="https://policies.google.com/privacy">Privacy Policy</a> and
        <a target="_blank" rel="noopener noreferrer" href="https://policies.google.com/terms">Terms of Service</a> apply.
    </p>


    </form>


    <!--Used to have {{ object.subjects }} next to  -->
    {% for object in object_list %}
        <a class="course_list_link" href="{{ object.get_absolute_url }}"> <p class = "course_list_border"> <strong> {{ object }} </strong> <br/> <br/>    {{ object.description }} <br/><br/>  {{ object.skill_level }}  &emsp; {{ object.created_at }}  &emsp; Views: {{ object.visited_times }} &emsp; 
        {% for sub in object.subjects.all %}
            {{ sub.name }}
        {% endfor %} </p> </a>
    {% endfor %}
  • Views.py:
    class CourseListView(ListView):
        template_name = 'courses/course_list.html'
    ​
        def get_queryset(self):
            return Course.objects.all()
    ​
        def get(self, request, *args, **kwargs):
            form = CourseForm(request.GET)
            queryset = self.get_queryset()
            if form.is_valid():
                queryset = queryset.filter(**{k: v for k, v in form.cleaned_data.items() if v})
            self.object_list = queryset
            return self.render_to_response(self.get_context_data(form=form,object_list=queryset,))

  • Forms.py:
class CourseForm(forms.Form):
  title__icontains = forms.CharField(widget=forms.TextInput(attrs={'class':'form-control col-12', 'autocomplete':'off', 'id':'title_contains', 'type':'search', 'placeholder': 'Course Name'}), required=False)
  visited_times__gte = forms.IntegerField(widget=forms.NumberInput(attrs={'class':'form-control', 'autocomplete':'off','id':'view_count_max', 'type':'number', 'min':'0', 'placeholder': '0'}), required=False, validators=[MinValueValidator(0), MaxValueValidator(99999999999999999999999999999999999)])
  visited_times__lte = forms.IntegerField(widget=forms.NumberInput(attrs={'class':'form-control', 'autocomplete':'off', 'id':'view_count_min', 'type':'number', 'min':'0', 'placeholder': '1000000'}), required=False, validators=[MinValueValidator(0), MaxValueValidator(99999999999999999999999999999999999)])
  created_at__gte = forms.DateField(widget=forms.TextInput(attrs={'class':'form-control', 'autocomplete':'off', 'id':'date_max','type':'date', 'placeholder': 'mm/dd/yyy'}), required=False)
  created_at__lte = forms.DateField(widget=forms.TextInput(attrs={'class':'form-control', 'autocomplete':'off', 'id':'date_min', 'type':'date', 'placeholder': 'mm/dd/yyy'}), required=False)
  skill_level = forms.ChoiceField(widget=forms.Select(attrs={'class':'form-control', 'autocomplete':'off','id':'skill_level'}), choices = ([('',''), ('Beginner','Beginner'), ('Intermediate','Intermediate'),('Advanced','Advanced'), ]), required=False)
  subjects = forms.ModelChoiceField(queryset=Subject.objects.all().order_by('name'), empty_label="", widget=forms.Select(attrs={'class':'form-control', 'autocomplete':'off', 'id':'subjects'}), required=False)

  # the new bit we're adding
  def __init__(self, *args, **kwargs):
      super(CourseForm, self).__init__(*args, **kwargs)
      self.fields['title__icontains'].label = "Course Name:"
      self.fields['visited_times__gte'].label = "Min Views:"
      self.fields['visited_times__lte'].label = "Max Views:"
      self.fields['created_at__gte'].label = "Min Date:"
      self.fields['created_at__lte'].label = "Max Date:"
      self.fields['skill_level'].label = "Skill Level:"
      self.fields['subjects'].label = "Subject:"
      self.fields['subjects'].queryset = Subject.objects.filter()
  • Models.py:

class Subject(models.Model):
    SUBJECT_CHOICES = ()
    name = models.CharField(max_length=20,choices=SUBJECT_CHOICES)

    def __str__(self):
        return self.name
​
    class Meta:
        ordering = ('name',)
​
class Course(models.Model):
​
SKILL_LEVEL_CHOICES = (
    ('Beginner', 'Beginner'),
    ('Intermediate', 'Intermediate'),
    ('Advanced', 'Advanced'),
)
​
slug = models.SlugField()
title = models.CharField(max_length=120)
description = models.TextField()
allowed_memberships = models.ManyToManyField(Membership)
created_at = models.DateTimeField(auto_now_add=True)
subjects = models.ManyToManyField(Subject)
skill_level = models.CharField(max_length=20,choices=SKILL_LEVEL_CHOICES, null=True)
visited_times = models.PositiveIntegerField(default=0)

def __str__(self):
    return self.title

def get_absolute_url(self):
    return reverse('courses:detail', kwargs={'slug': self.slug})

@property
def lessons(self):
    return self.lesson_set.all().order_by('position')
​
class Meta:
    ordering = ('title',)

我尝试遵循一些教程 Django docs one,但不确定如何将分页代码嵌入到我的中。

https://docs.djangoproject.com/en/3.0/topics/pagination/

如果有人能帮我解决这个问题,我将不胜感激。

【问题讨论】:

  • 欢迎来到 SO。请始终在此处包含您的代码(在代码块内)。
  • @Pedram Parsian 好吧抱歉不知道。我看看能不能编辑一下。
  • @hectares 您可以使用edit 将代码复制到您的问题中。然后使用代码格式化。
  • @SecretAgentMan 好的不知道,谢谢!

标签: python django search pagination


【解决方案1】:

搜索表单(html):

 <!-- Search Form -->
        <form class="navbar-search navbar-search-dark form-inline mr-3 d-none d-md-flex ml-lg-auto" action="{% url 'search' %}" method="get">
          <div class="form-group mb-0">
           <input class="form-control mr-sm-2" type="search" placeholder="Search Tasks" aria-label="Search" name="q">
           <button class="btn btn-outline-white my-2 my-sm-0" type="submit">Search</button>
          </div>
        </form>

views.py

class SearchView(ListView):  # taskları arama sonucu listeliyoruz
    model = Task
    template_name = 'task/search.html'
    paginate_by = 5
    context_object_name = 'task'

    def get_queryset(self):
        query = self.request.GET.get("q")

        if query:
            return Task.objects.filter(
                Q(title__icontains=query) | Q(content__icontains=query) | Q(tag__title__icontains=query)).order_by(
                'id').distinct()

        return Task.objects.all().order_by('id')

在您想使用分页的任何字段中,在此处编写代码(例如 category_detail.html):

<div class="card-footer py-4">
                {% if is_paginated %}
              <nav aria-label="...">
                <ul class="pagination justify-content-end mb-0">
                    {% if page_obj.has_previous %}
                  <li class="page-item">
                    <a class="page-link" href="?page={{ page_obj.previous_page_number }}" tabindex="-1">
                      <i class="fas fa-angle-left"></i>
                      <span class="sr-only">Previous</span>
                    </a>
                  </li>

                   {% else %}

                     <li class="page-item disabled">
                    <a class="page-link" href="#" tabindex="-1">
                      <i class="fas fa-angle-left"></i>
                      <span class="sr-only">Previous</span>
                    </a>
                  </li>

                    {% endif %}

                    {% for i in paginator.page_range %}
                    {% if page_obj.number == i %}
                  <li class="page-item active">
                    <a class="page-link" href="#"> {{ i }} </a>
                  </li>
                     {% else %}
                  <li class="page-item">
                    <a class="page-link" href="?page={{ i }}">{{ i }}<span class="sr-only">(current)</span></a>
                  </li>
                    {% endif %}
                    {% endfor %}

                     {% if page_obj.has_next %}
                  <li class="page-item">
                    <a class="page-link" href="?page={{ page_obj.next_page_number }}">
                      <i class="fas fa-angle-right"></i>
                      <span class="sr-only">Next</span>
                    </a>
                  </li>

                    {% else %}

                     <li class="page-item disabled">
                    <a class="page-link" href="#">
                      <i class="fas fa-angle-right"></i>
                      <span class="sr-only">Next</span>
                    </a>
                  </li>
                    {% endif %}

                </ul>
              </nav>
                {% endif %}
            </div>

我希望这些示例对你有用。

【讨论】:

    【解决方案2】:

    请编辑以包含您的代码。

    在您链接到的页面中,阅读此部分:

    https://docs.djangoproject.com/en/3.0/topics/pagination/#paginating-a-listview

    你只需要把它添加到你的 ListView 中

    paginate_by = N
    

    然后添加

    <div class="pagination">
        <span class="step-links">
            {% if contacts.has_previous %}
                <a href="?page=1">&laquo; first</a>
                <a href="?page={{ contacts.previous_page_number }}">previous</a>
            {% endif %}
    
            <span class="current">
                Page {{ contacts.number }} of {{ contacts.paginator.num_pages }}.
            </span>
    
            {% if contacts.has_next %}
                <a href="?page={{ contacts.next_page_number }}">next</a>
                <a href="?page={{ contacts.paginator.num_pages }}">last &raquo;</a>
            {% endif %}
        </span>
    </div>
    

    到 course_list.html。

    【讨论】:

    • 我在 course_list.html 中将“联系人”更改为什么?结果正确显示了基于 X 数字的 paginate_by,这很好。您提供的 HTML 仅显示“ Page of .”
    • 如果您在问题中包含代码会更容易回答。嗯,文档对此有点简洁。看起来应该是page_obj
    • 抱歉,我注意到了一件事!如果您搜索特定课程名称(如“Test”)并且您有 3 个不同的课程名为“Test”但 paginate_by 只有 2,则过滤后的搜索不会通过单击下一个或上一个按钮为该过滤器保存自身 - 过滤器只是重置为单击下一个或上一个后再次默认。您将如何保存搜索条件以使用分页?然后重置搜索条件以再次显示整个分页?
    • 有点像一个按钮或链接来切换删除搜索条件或保留分页的搜索条件
    • 我将如何使用 querydict = self.request.GET.copy() querydict.urlencode() 并将其传递给视图的上下文是否可行?
    猜你喜欢
    • 1970-01-01
    • 2021-10-03
    • 2021-06-11
    • 2019-01-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-14
    • 2020-03-27
    相关资源
    最近更新 更多