web-dev-qa-db-ja.com

Django ListView-フィルタリングおよびソートするフォーム

私の目標

  • すべての更新(モデル)をテーブルにリストするサイト
  • 一度にすべてのモデルを表示しないでください(ページ付け-ページあたり10)
  • リストをフィルタリングして並べ替える

私の考え

  • ListViewを使用して、すべての更新のセットを取得できます
  • Paginate_by = 10を使用
  • フォームを使用して、クエリセットでorder_byまたはフィルターを設定する

私の問題

フィルターと並べ替えを使用してクエリセットを変更するフォームを追加する方法がわかりません。私のアイデアは、追加のフィルターとorder_byを使用してget_querysetのクエリを変更することでした。

マイビュー

class MyView(ListView):
    model = Update
    template_name = "updates/update.html"
    paginate_by = 10

    def get_queryset(self):
        return Update.objects.filter(
            ~Q(state=Update.STATE_REJECTED),
            ~Q(state=Update.STATE_CANCELED),
            ~Q(state=Update.STATE_FINISHED),
        ).order_by(
            'planned_release_date'
        )

私の考え

このようなもの。私はそれがこのように機能していないことを知っています...単に説明するために

class MyView(ListView):
    model = Update
    template_name = "updates/update.html"
    paginate_by = 10

    def post(self, request, *args, **kwargs):
        new_context = Update.objects.filter(
            request.POST.get("filter"),
        ).order_by(
            request.POST.get("sorting"),
        )

    def get_queryset(self):
        return Update.objects.filter(
            ~Q(state=Update.STATE_REJECTED),
            ~Q(state=Update.STATE_CANCELED),
            ~Q(state=Update.STATE_FINISHED),
        ).order_by(
            'planned_release_date'
        )
15
Rooterle

投稿は必要ありません。フィルター値とorder_byをURLで渡します。例:

.../update/list/?filter=filter-val&orderby=order-val

そして、次のようにget_querysetでフィルターとorderbyを取得します。

class MyView(ListView):
    model = Update
    template_name = "updates/update.html"
    paginate_by = 10

    def get_queryset(self):
        filter_val = self.request.GET.get('filter', 'give-default-value')
        order = self.request.GET.get('orderby', 'give-default-value')
        new_context = Update.objects.filter(
            state=filter_val,
        ).order_by(order)
        return new_context

    def get_context_data(self, **kwargs):
        context = super(MyView, self).get_context_data(**kwargs)
        context['filter'] = self.request.GET.get('filter', 'give-default-value')
        context['orderby'] = self.request.GET.get('orderby', 'give-default-value')
        return context

フィルターとorderbyに適切なデフォルト値を与えるようにしてください

フォームの例(必要に応じて変更できます):

<form method="get" action="{% url 'update-list' %}">
    <p>Filter: <input type="text" value={{filter}} name="filter"/></p>
    <p>order_by: <input type="text" value={{orderby}} name="orderby"/></p>
    <p><input type="submit" name="submit" value="submit"/></p>
</form>
25
Anush Devendra

なぜここでこのクールなライブラリについて誰も言及しなかったのかと思います:Django-filterhttps://github.com/carltongibson/Django-filter

非常にクリーンにフィルタリングするためのロジックを定義し、高速で動作するフォームなどを取得できます。

ここのデモ: https://stackoverflow.com/a/46492378/95355

6
andilabs

私はこれを他の場所に投稿しましたが、これは選択した回答に追加されると思います。

Get_context_dataを使用してこれを行うことをお勧めします。手動でHTMLフォームを作成し、GETを使用してこのデータを取得します。私が書いたものの例を以下に示します。フォームを送信すると、取得データを使用して、コンテキストデータを介して戻すことができます。この例はリクエストに合わせたものではありませんが、他のユーザーの助けになるはずです。

def get_context_data(self, **kwargs):
    context = super(Search, self).get_context_data(**kwargs)
    filter_set = Gauges.objects.all()
    if self.request.GET.get('gauge_id'):
        gauge_id = self.request.GET.get('gauge_id')
        filter_set = filter_set.filter(gauge_id=gauge_id)

    if self.request.GET.get('type'):
        type = self.request.GET.get('type')
        filter_set = filter_set.filter(type=type)

    if self.request.GET.get('location'):
        location = self.request.GET.get('location')
        filter_set = filter_set.filter(location=location)

    if self.request.GET.get('calibrator'):
        calibrator = self.request.GET.get('calibrator')
        filter_set = filter_set.filter(calibrator=calibrator)

    if self.request.GET.get('next_cal_date'):
        next_cal_date = self.request.GET.get('next_cal_date')
        filter_set = filter_set.filter(next_cal_date__lte=next_cal_date)

    context['gauges'] = filter_set
    context['title'] = "Gauges "
    context['types'] = Gauge_Types.objects.all()
    context['locations'] = Locations.objects.all()
    context['calibrators'] = Calibrator.objects.all()
    # And so on for more models
    return context
4
Sherd