Partage
  • Partager sur Facebook
  • Partager sur Twitter

[ Django ] object.filter

Filtrer uniquement si les variables ne sont pas vides

    15 novembre 2019 à 16:32:54

    Bonjour,

    Je récupère des données d'un formulaire de recherche et j'aimerais filtrer avec ces données.

    def list_annonce(request):
    
        form = SearchForm(request.POST or None)
        # Nous vérifions que les données envoyées sont valides
        # Cette méthode renvoie False s'il n'y a pas de données 
        # dans le formulaire ou qu'il contient des erreurs.
        if form.is_valid(): 
            # Ici nous pouvons traiter les données du formulaire
            typeDeBien = form.cleaned_data['typeDeBien']
            reference = form.cleaned_data['reference']
            budgetmin = form.cleaned_data['budgetmin']
            budgetmax = form.cleaned_data['budgetmax']
    
            annonces = Annonce.objects.filter(typeDeBien=typeDeBien, reference=reference, prix__lte=budgetmax, prix__gte=budgetmin) 
        else:
            annonces = Annonce.objects.all()
    
        return render(request, 'liste.html', {'liste_annonces': annonces})

    ça fonctionne bien si je rentre 4 valeurs sauf que, dans mon formulaire, la reference, et le budgetmin/max sont en

    required=False

    Du coup, si par exemple, je laisse référence à vide dans le formulaire de recherche, je n'obtiens aucun résultat.

    C'est quoi la meilleur façon de dire en gros, filtre sur référence uniquement si reférence != "" ?

    Merci



    • Partager sur Facebook
    • Partager sur Twitter
      15 novembre 2019 à 18:24:57

      Bonsoir,

      J'ai pas tout compris... Peux-tu montrer ton modèle lié à ton formulaire ?

      Tu as mis des valeurs par défaut pour budgetmin et budgetmax ?

      • Partager sur Facebook
      • Partager sur Twitter

      Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
      La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

        15 novembre 2019 à 18:48:30

        Oui bien sur si ça peut aider.

        class Annonce(models.Model):
            # Details
            titre = models.CharField(max_length=100, null=False)
            contenu = models.TextField(null=False)
            prix = models.IntegerField(null=False)
            typeDeBien = models.ForeignKey('CategorieBien', on_delete=models.CASCADE, null=True, blank=True)
            typeDannonce = models.ForeignKey('CategorieAnnonce', on_delete=models.CASCADE, null=True, blank=True)
            reference = models.CharField(null=False, max_length=12)
            class Meta:
                verbose_name = "annonce"
                ordering = ['date']
            
            def __str__(self):
                """ 
                Cette méthode que nous définirons dans tous les modèles
                nous permettra de reconnaître facilement les différents objets que 
                nous traiterons plus tard dans l'administration
                """
                return self.titre
        
        class CategorieBien(models.Model):
            # Details
            libelle = models.CharField(max_length=80, null=False)
            
            class Meta:
                verbose_name = "CategorieBien"
                ordering = ['libelle']
            
            def __str__(self):
                """ 
                Cette méthode que nous définirons dans tous les modèles
                nous permettra de reconnaître facilement les différents objets que 
                nous traiterons plus tard dans l'administration
                """
                return self.libelle
        
        class CategorieAnnonce(models.Model):
            # Details
            libelle = models.CharField(max_length=80, null=False)
            
            class Meta:
                verbose_name = "CategorieAnnonce"
                ordering = ['libelle']
            
            def __str__(self):
                """ 
                Cette méthode que nous définirons dans tous les modèles
                nous permettra de reconnaître facilement les différents objets que 
                nous traiterons plus tard dans l'administration
                """
                return self.libelle



        Le formulaire :

        class SearchForm(forms.Form):
            typeDeBien = forms.ModelChoiceField(queryset=CategorieBien.objects.all(), label="Type de bien", required=False)
            reference = forms.CharField(max_length=100, label='Référence', required=False)
        
            TARIF_CHOICE = (
                (0, ('0')),
                (100000, ('100 000'))
                (200000, ('200 000')),
            )
        
            budgetmin = forms.ChoiceField(choices=(TARIF_CHOICE), required=False, label="Budget min")
            budgetmax = forms.ChoiceField(choices=(TARIF_CHOICE), required=False, initial=2, label="Budget max")
        
        


        Comme on peut le voir "reference" par exemple est en

        required=False

        Du coup, si dans mon formulaire je remplis tous les champs dont une référence exacte j'ai bien l'annonce que je souhaite. Mais, je veux pouvoir sélectionner un ordre de prix et laisser le champ référence à vide. Si je fais ça, avec mon code actuel, il va rechercher dans la base de données les annonces avec référence == "".

        Hors ce n'est pas ce que je souhaite. Je veux que si reference != "", il cherche les annonces portant la référence donnée dans le formulaire. Si je ne rentre pas de reference dans le formulaire, je ne souhaite pas que cette valeur soit prise en compte.

        En php, j'aurais pu faire un truc comme ça en gros :

        $p = "";
        if(!is_null($element)){
           $p = " AND element=$element";
        }
        
        $sql = "Select * from annonces where prix > $budgetmin".$p
        


        Mais je ne vois pas comment le faire en python.

        • Partager sur Facebook
        • Partager sur Twitter
          15 novembre 2019 à 19:38:27

          Je pense qu'il faut que tu dépaquete un dictionnaire pour y arriver pas trop salement:

           if form.is_valid():
                  # Ici nous pouvons traiter les données du formulaire
                  valeur = ['typeDeBien', 'reference', 'budgetmin', 'budgetmax']
                  filtre = {v:form.cleaned_data[v] for v in valeurs if v}
           
                  annonces = Annonce.objects.filter(**filtre)
              else:
                  annonces = Annonce.objects.all()
           
              return render(request, 'liste.html', {'liste_annonces': annonces})
          



          -
          Edité par Coliculus 15 novembre 2019 à 19:38:43

          • Partager sur Facebook
          • Partager sur Twitter
            15 novembre 2019 à 21:30:53

            Je sais pas ce qui est plus propre, peut-être je passerai par la méthode has_changed...
            • Partager sur Facebook
            • Partager sur Twitter

            Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
            La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

              16 novembre 2019 à 10:13:16

              Merci à vous deux.

              Au final, j'ai utilisé has_changed, ça me semble mieux vu que c'est intégré directement à django.

              • Partager sur Facebook
              • Partager sur Twitter
                16 novembre 2019 à 11:10:01

                Si tout est bon, on peut mettre ce sujet en résolu
                • Partager sur Facebook
                • Partager sur Twitter

                Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
                La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

                [ Django ] object.filter

                × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                • Editeur
                • Markdown