【问题标题】:How can I order/sort a filtered search query and render it on another template on Django?如何对过滤后的搜索查询进行排序/排序并将其呈现在 Django 的另一个模板上?
【发布时间】:2021-01-02 04:45:57
【问题描述】:

我正在尝试更改 Django 上过滤搜索查询的顺序。我正在为我的搜索视图使用基于类的 ListView。我能够从搜索中呈现过滤后的查询集,但是如何更改具有相同搜索的相同查询集的顺序并将其呈现在另一个页面上。有点像 twitter 如何按 top 或 new 排序搜索。我尝试制作不同的视图并更改顺序,但我不确定如何将相同的搜索查询转换为新视图。请帮忙!下面是我的代码。

views.py

class search_view(ListView):
    model = Post
    template_name = 'main/search.html'
    context_object_name = 'posts'
    paginate_by = 2
     # searches through everything using Q import 
    def get_queryset(self, *args, **kwargs):
          
          q = self.request.GET.get('q')
          self.posts = Post.objects.filter(
             Q(ticker__icontains=q) |
             Q(user__username__icontains=q) |
             Q(content__icontains=q) |
             Q(tags__name__icontains=q) 
          ).annotate(
               upvoted=Exists(Post.upvotes.through.objects.filter(
                    user_id=self.request.user.id,
                    post_id=OuterRef('pk')
            ))).order_by('-date_traded')
          return self.posts

模板.html

<a class="btn btn-secondary dropdown-toggle mb-3 ml-2" href="#" role="button" id="dropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
          Sort
        </a>
        <div class="dropdown-menu" aria-labelledby="dropdownMenuLink">
            <a class="dropdown-item" href='?q={{ request.GET.q }}'>New</a>
            <a class="dropdown-item" href="#">Top</a> <!-- I would like to render the newly sorted results from here-->
        </div>

<!-- the get request for the query-->
<form class="form-inline" method="GET" action="{% url 'main:search' %}">
    <input class="form-control mt-2 mr-sm-2" type="search" placeholder="Search by ticker/tags" aria-label="Search" name="q">
    <button class="btn btn-outline-info mt-2 mr-sm-2" type="submit" value="Search">Search</button>
</form>

【问题讨论】:

    标签: python django search django-views django-class-based-views


    【解决方案1】:

    通常您会使用第二个获取参数order_by,假设它看起来像:如果您只是将order_by 值传递给查询集排序,domain.com/view/?q=searchterm&amp;order_by=-date_traded 将保留当前功能。

    在此更改后,您可以在模板中添加任何带有 href 的标签,并将所需的 order_by 作为参数。

    更新视图以支持第二个参数:

    class search_view(ListView):
        model = Post
        template_name = 'main/search.html'
        context_object_name = 'posts'
        paginate_by = 2
         # searches through everything using Q import 
        def get_queryset(self, *args, **kwargs):
              q = self.request.GET.get('q')
              order_by = self.request.GET.get('order_by', '-date_traded')
              self.posts = Post.objects.filter(
                 Q(ticker__icontains=q) |
                 Q(user__username__icontains=q) |
                 Q(content__icontains=q) |
                 Q(tags__name__icontains=q)
              ).annotate(
                   upvoted=Exists(Post.upvotes.through.objects.filter(
                        user_id=self.request.user.id,
                        post_id=OuterRef('pk')
                ))).order_by(order_by)
              return self.posts
    

    还有模板:

    <a class="btn btn-secondary dropdown-toggle mb-3 ml-2" href="#" role="button" id="dropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
              Sort
            </a>
            <div class="dropdown-menu" aria-labelledby="dropdownMenuLink">
                <a class="dropdown-item" href='?q={{ request.GET.q
                }}&order_by=-date_traded'>New</a>
                <a class="dropdown-item" href='?q={{ request.GET.q
                }}&order_by=-other_field'>Top</a> <!-- I would like to render the newly sorted results from here-->
            </div>
    
    <!-- the get request for the query-->
    <form class="form-inline" method="GET" action="{% url 'main:search' %}">
        <input class="form-control mt-2 mr-sm-2" type="search" placeholder="Search by ticker/tags" aria-label="Search" name="q">
        <button class="btn btn-outline-info mt-2 mr-sm-2" type="submit" value="Search">Search</button>
    </form>
    

    编辑。所以为了澄清我相信相同的视图和相同的模板应该适用于这个用例,只是查询集的顺序不同。如果没有,请更新要求。

    【讨论】:

    • 这是否意味着制作一个单独的视图来处理模板上的任何内容的排序?
    • 不,请查看我的编辑。你真的需要一个新的视图或模板吗?如果可能的话,我建议只增强当前的一个以支持多个排序。
    • 对不起,你的意思是我应该为不同的订单做第二个 get_queryset 吗?我怎么能参考第二组?
    • 我还在视图和模板中添加了更新的代码(a 标签的 href 属性)
    • 非常感谢。你是巫师大卫!!我希望你有一个美好的一天:) 我仍然是一个初学者,这个逻辑很简单但是很天才!谢谢你的课。
    【解决方案2】:

    我也遇到过类似的情况。我尝试使用 FBV。下面的代码对我的情况进行了排序:

    def songs(request, filter_by):
    if not request.user.is_authenticated:
        return render(request, 'music/login.html')
    else:
        try:
            song_ids = []
            for album in Album.objects.all():
                for song in album.song_set.all():
                    song_ids.append(song.pk)
            users_songs = Song.objects.filter(pk__in=song_ids)
            if filter_by == 'favorites':
                users_songs = users_songs.filter(is_favorite=True)
        except Album.DoesNotExist:
            users_songs = []
        return render(request, 'music/songs.html', {
            'song_list': users_songs,
            'filter_by': filter_by,
        })
    

    希望这会对您有所帮助。就像@david 说的你不需要另一个模板或视图。

    【讨论】:

      猜你喜欢
      • 2015-10-06
      • 2013-01-25
      • 2021-04-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多