Dropdown select option to filter a Django list

14,664

Solution 1

I can see what you mean coming from Angular. The most classical way of doing that in Django would be creating a form with all the fields you need, then passing it to the view to process the data, filter records and pass them back to the template. I'll try to provide a basic example so you can hopefully get the idea:

Index.html:

<form action="{% url 'index' %}" method="get">
    <label for="featured">Format</label>
    <select name="featured">
        <option value="Yes" />Yes</option>
        <option value="No" />No</option>
    <input type="submit" name="featured" value="Filter" />
</form>     

Views.py

def index(request, template_name='index.html'):

    if request.GET.get('featured'):
        featured_filter = request.GET.get('featured')
        listings = Listing.objects.filter(featured_choices=featured_filter)
    else:
        listings = Listing.objects.all()

    context_dict = {'listings': listings}
    return render(request, template_name, context_dict)

This is pretty self-explanatory. If there's a "featured" parameter in GET, list will get filtered, otherwise it will pass all objects. Obviously we're looking at page refresh every filter request, if you expect a bit more of a one-page experience, you have to go for ajax and post requests, or something. Also, keep in mind this snippet is just a hard-coded example. Ideally, you would want to create a ModelForm class and instantiate that, then pass it to the template - a lot more readable and maintainable if you have more filter fields. If there's complex filtering involved, you would also probably want to have an additional view for filtering purposes, but this works too, it just gets messy really quick.

Solution 2

Thanks for Zephi, your tip helped me a lot, but for me, only worked after I changed index.html to this:

index.html

<form action="{% url 'index' %}" method="get">
    <label for="featured">Format</label>
    <select name="featured">
        <option value="Yes" />Yes</option>
        <option value="No" />No</option>
    </select>   <!-- ADDED THIS LINE -->
    <input type="submit" value="Filter" />   <!-- DELETE name="featured" FROM ORIGINAL CODE -->  
</form>

here fragments from my app's code:

index.html

<form action="{% url 'index' %}" method="get">
    <label for="featured">Format</label>
    <select name="featured">
        {% for adoption in typeList %} 
            <option value="{{ adoption }}">{{ adoption }}</option>
        {% endfor %}
     </select>
     <input type="submit" value="Filter" />
</form>

views.py

def index(request, template_name='index.html'):
    if request.GET.get('featured'):
        featured_filter = request.GET.get('featured')
        query = Unit.listType.filter(unitType=featured_filter)
    else:
        query = Unit.listType.all()
    typeList = query.order_by('unitType').values_list('unitType',flat=True).distinct()
    _dict = {}
    for x in range(len(typeList)):
        _dict[typeList[x]] = typeList[x]
    return render(request, 'index.html', {'query':query, 'typeList':_dict})
Share:
14,664

Related videos on Youtube

Charles Smith
Author by

Charles Smith

Updated on July 05, 2022

Comments

  • Charles Smith
    Charles Smith almost 2 years

    Coming from Angular, this was easy to do, but I am not sure where to begin on creating a dropdown form that will filter from a list of objects. Basically, I have the code below, that will pull in and display all real estate listings; I would like to create a dropdown that will have 2 selections, 'Featured' and 'New Listing' and when a user selects one, the list will filter out and display only those listings that match. Thank you for your help.

    Here is my model

    from django.db import models
    from django.utils import timezone
    
    
    class Listing(models.Model):
        FAIR = 'FAIR'
        GOOD = 'GOOD'
        VERY_GOOD = 'VERY_GOOD'
        EXCELLENT = 'EXCELLENT'
    
        NEW_LISTING = 'NEW_LISTING'
        PRICE_REDUCED = 'PRICE_REDUCED'
        UNDER_AGREEMENT = 'UNDER_AGREEMENT'
        SOLD = 'SOLD'
    
        YES = 'YES'
        NO = 'NO'
    
        FULL_SERVICE = 'FULL_SERVICE'
        FOR_LEASE = 'FOR_LEASE'
        WITH_REAL = 'WITH_REAL'
        QUICK_SERVE = 'QUICK_SERVE'
    
        CONDITION_CHOICES = (
            ('FAIR', 'Fair'),
            ('GOOD', 'Good'),
            ('VERY_GOOD', 'Very Good'),
            ('EXCELLENT', 'Excellent'),
        )
    
        STATUS_CHOICES = (
            ('NEW_LISTING', 'New Listing'),
            ('PRICE_REDUCED', 'Price Reduced'),
            ('UNDER_AGREEMENT', 'Under Agreement'),
            ('SOLD', 'Sold'),
        )
    
        FEATURED_CHOICES = (
            ('YES', 'Yes'),
            ('NO', 'No'),
        )
    
        LOCATION_TYPE = (
            ('FULL_SERVICE', 'Full Service'),
            ('FOR_LEASE', 'For Lease'),
            ('WITH_REAL', 'With Real'),
            ('QUICK_SERVE', 'Quick Serve'),
        )
    
        photo = models.ImageField(upload_to="media/properties/", max_length=250, blank=True, null=True)
        broker = models.ForeignKey('auth.User')
        phone = models.CharField(max_length=20, null=True)
        title = models.CharField(max_length=250, null=True)
        description = models.TextField(null=True)
        concept = models.CharField(max_length=250, null=True)
        location = models.CharField(max_length=250, null=True)
        size = models.CharField(max_length=250, null=True)
        seating = models.CharField(max_length=250, null=True)
        condition_choices = models.CharField(max_length=20, choices=CONDITION_CHOICES, blank=True)
        hours = models.CharField(max_length=250, null=True)
        asking_price = models.CharField(max_length=250, null=True)
        sales_price = models.CharField(max_length=250, null=True)
        rent_price = models.CharField(max_length=250, null=True)
        lease_terms = models.CharField(max_length=250, null=True)
        licenses = models.CharField(max_length=250, null=True)
        parking = models.CharField(max_length=250, null=True)
        status_choices = models.CharField(max_length=20, choices=STATUS_CHOICES, blank=True, null=True)
        featured_choices = models.CharField(max_length=5, choices=FEATURED_CHOICES, blank=True, null=True)
        location_type = models.CharField(max_length=20, choices=LOCATION_TYPE, blank=True, null=True)
        created_date = models.DateTimeField(default=timezone.now, null=True)
        published_date = models.DateTimeField(default=timezone.now, null=True)
    
        listing_order = models.PositiveIntegerField(default=0, blank=False, null=False)
    
        class Meta(object):
            ordering = ('listing_order',)
    
        def publish(self):
            """This is a docstring"""
            self.published_date = timezone.now()
            self.save()
    
        def __str__(self):
            return self.title
    

    And here is my template

    {% extends "listing/base.html" %}{% load staticfiles %}
    
    {% block content %}
    
      <section class="listings mt64 mb64">
        <div class="container">
          {% for listing in listings %}
            <div class="row">
              <div class="col-md-4">
                <div class="listings-photo" style="background: #ccc url('{{ MEDIA_URL }}{{ listing.photo.name }}')no-repeat 50% 50%; background-size: cover; width: 350px; height: 220px"></div>
              </div>
              <div class="col-md-8">
                <h3 class="uppercase">{{ listing.title }}</h3>
    
                <p><span class="listings-title">Description:</span> {{ listing.description }}</p>
    
                <div class="row">
                  <div class="col-md-6">
                    <ul>
                      <li><span class="listings-title">Concept:</span> {{ listing.concept }}</li>
                      <li><span class="listings-title">Location:</span> {{ listing.location }}</li>
                      <li><span class="listings-title">Size:</span> {{ listing.size }}</li>
                      <li><span class="listings-title">Seating:</span> {{ listing.seating }}</li>
                      <li><span class="listings-title">Condition:</span> {{ listing.condition_choices }}
                      </li>
                      <li><span class="listings-title">Hours:</span> {{ listing.hours }}</li>
                    </ul>
                  </div>
                  <div class="col-md-6">
                    <ul>
                      <li><span class="listings-title">Asking Price:</span> {{ listing.asking_price }}
                      </li>
                      <li><span class="listings-title">Sales:</span> {{ listing.sales_price }}</li>
                      <li><span class="listings-title">Rent:</span> {{ listing.rent_price }}</li>
                      <li><span class="listings-title">Lease Terms:</span> {{ listing.lease_terms }}</li>
                      <li><span class="listings-title">Licenses:</span> {{ listing.licenses }}</li>
                      <li><span class="listings-title">Parking:</span> {{ listing.parking }}</li>
                    </ul>
                  </div>
                </div>
                <p>For more information please contact {{ user.first_name }} {{ user.last_name }} at {{ listing.phone }}.</p>
              </div>
            </div>
          {% endfor %}
        </div>
      </section>
    
    {% endblock content %}