用于过滤 Django 列表的下拉 select 选项
Dropdown select option to filter a Django list
来自 Angular,这很容易做到,但我不确定从哪里开始创建将从对象列表中过滤的下拉表单。基本上,我有下面的代码,它将拉入并显示所有房地产清单;我想创建一个下拉列表,其中有 2 个选项,'Featured' 和 'New Listing',当用户选择一个时,列表将过滤掉并仅显示匹配的列表。谢谢你的帮助。
这是我的模型
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 %}
我从 Angular 明白你的意思了。在 Django 中最 classical 的方法是创建一个包含您需要的所有字段的表单,然后将其传递给视图以处理数据、过滤记录并将它们传递回模板。我将尝试提供一个基本示例,希望您能理解:
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 中有 "featured" 参数,列表将被过滤,否则将传递所有对象。显然,我们正在查看每个过滤器请求的页面刷新,如果您希望获得更多的单页体验,则必须选择 ajax 和 post 请求或其他方式。另外,请记住此代码段只是一个硬编码示例。理想情况下,您会希望创建一个 ModelForm class 并对其进行实例化,然后将其传递给模板 - 如果您有更多筛选字段,则可读性和可维护性会更高。如果涉及复杂的过滤,您可能还希望有一个额外的视图用于过滤目的,但这也有效,它很快就会变得混乱。
感谢 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})
来自 Angular,这很容易做到,但我不确定从哪里开始创建将从对象列表中过滤的下拉表单。基本上,我有下面的代码,它将拉入并显示所有房地产清单;我想创建一个下拉列表,其中有 2 个选项,'Featured' 和 'New Listing',当用户选择一个时,列表将过滤掉并仅显示匹配的列表。谢谢你的帮助。
这是我的模型
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 %}
我从 Angular 明白你的意思了。在 Django 中最 classical 的方法是创建一个包含您需要的所有字段的表单,然后将其传递给视图以处理数据、过滤记录并将它们传递回模板。我将尝试提供一个基本示例,希望您能理解:
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 中有 "featured" 参数,列表将被过滤,否则将传递所有对象。显然,我们正在查看每个过滤器请求的页面刷新,如果您希望获得更多的单页体验,则必须选择 ajax 和 post 请求或其他方式。另外,请记住此代码段只是一个硬编码示例。理想情况下,您会希望创建一个 ModelForm class 并对其进行实例化,然后将其传递给模板 - 如果您有更多筛选字段,则可读性和可维护性会更高。如果涉及复杂的过滤,您可能还希望有一个额外的视图用于过滤目的,但这也有效,它很快就会变得混乱。
感谢 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})