下拉选择选项以过滤Django列表

时间:2015-11-16 00:18:23

标签: django django-models django-forms django-templates django-views

来自Angular,这很容易做到,但我不知道从哪里开始创建一个将从对象列表中过滤的下拉表单。基本上,我有下面的代码,它将引入并显示所有房地产列表;我想创建一个有两个选项的下拉列表,'精选'和'新上市'当用户选择一个时,列表将过滤掉并仅显示匹配的列表。谢谢你的帮助。

这是我的模特

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

这是我的模板

{% 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 %}

2 个答案:

答案 0 :(得分:5)

我可以看到你的意思来自Angular。在Django中最经典的方法是创建一个包含所需字段的表单,然后将其传递给视图以处理数据,过滤记录并将其传递回模板。我将尝试提供一个基本示例,以便您可以获得这个想法:

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

这是非常不言自明的。如果GET中有“特色”参数,列表将被过滤,否则它将传递所有对象。显然我们正在查看每个过滤器请求的页面刷新,如果你期望更多的单页体验,你必须去ajax和发布请求,或者其他东西。另外,请记住这段代码只是一个硬编码的例子。理想情况下,您可能希望创建一个ModelForm类并将其实例化,然后将其传递给模板 - 如果您有更多的过滤器字段,则更具可读性和可维护性。如果涉及复杂的过滤,你可能还想要一个额外的视图用于过滤目的,但这也有效,它只是很快就会变得混乱。

答案 1 :(得分:1)

感谢Zephi,您的技巧对我有很大帮助,但对我来说,只有在将index.html更改为以下内容后,它才能起作用:

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>

此处是我的应用代码的片段:

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