web-dev-qa-db-fra.com

Django ListView - Formulaire pour filtrer et trier

Mon objectif

  • Un site qui répertorie toutes mes mises à jour (modèle) dans un tableau
  • N'affiche pas tous les modèles à la fois (pagination - peut-être 10 par page)
  • Filtrer et trier la liste

Mes pensées

  • Je peux utiliser ListView pour obtenir un ensemble de toutes mes mises à jour
  • Utilisez paginate_by = 10
  • Utiliser un formulaire pour définir order_by ou filtrer dans mon QuerySet

Mon problème

Je ne sais pas comment ajouter un formulaire pour modifier mon QuerySet avec filtre et tri. Mon idée était de modifier la requête dans get_queryset avec un filtre supplémentaire et order_by.

Ma vue

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'
        )

Mon idée

Quelque chose comme ça. Je sais que ça ne fonctionne pas comme ça ... juste pour illustrer

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

Vous n'avez pas besoin de poste. Passez la valeur du filtre et order_by dans l'url par exemple:

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

et obtenez le filtre et orderby dans le get_queryset comme:

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

Assurez-vous de donner la valeur par défaut appropriée au filtre et à la commande

Exemple de formulaire (vous pouvez le modifier selon vos besoins):

<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

Je me demande pourquoi personne n'a mentionné ici cette bibliothèque sympa: Django-filterhttps://github.com/carltongibson/Django-filter

vous pouvez définir votre logique de filtrage très propre et obtenir des formulaires de travail rapides, etc.

démo ici: https://stackoverflow.com/a/46492378/95355

6
andilabs

J'ai posté cela ailleurs mais je pense que cela ajoute à la réponse sélectionnée.

Je pense que vous feriez mieux de le faire via get_context_data. Créez manuellement votre formulaire HTML et utilisez GET pour récupérer ces données. Un exemple de quelque chose que j'ai écrit est ci-dessous. Lorsque vous soumettez le formulaire, vous pouvez utiliser les données d'obtention pour les transmettre via les données de contexte. Cet exemple n'est pas adapté à votre demande, mais il devrait aider les autres utilisateurs.

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