情景:
产品可以在数据库中定义多个属性,我希望能够按这些属性进行过滤。
由于我还没有找到使用django-filter来使用动态属性的方法,目前这是通过使用django filter MethodFilter
实现的,它将作为查询字符串传递的属性解析为:
/products?attribute=size_2&attribute=color_red
像这样的网址被解析并且有效。
问题在于建立网址:
我找不到合理的方法来构建网址,这会考虑当前的搜索参数并添加/替换这些参数。
Django似乎强迫我使用urlconf,但django-filter使用查询字符串参数。
我试图实现的是:
用户在页面/products?attribute=size_10
上显示所有具有该尺寸的产品。
当他点击“红色”链接时,新网址变为:/products?attribute=size_10&attribute=color_red
你能指点我实现这个的 django方式吗?
答案 0 :(得分:0)
如果在中间件中包含"django.core.context_processors.request",
然后可以在模板中访问request.get。
然后您可以构建一个过滤器,在构建您正在讨论的链接时返回所需的“GET”变量。
这是我做过的代码:
@register.simple_tag(takes_context=True)
def lessonapp_preserved_filters(context, url, dayofweek):
opts = context.get('opts')
preserved_filters = context.get('preserved_filters')
parsed_url = list(urlparse(url))
parsed_qs = dict(parse_qsl(parsed_url[4]))
merged_qs = dict()
if opts and preserved_filters:
preserved_filters = dict(parse_qsl(preserved_filters))
match_url = '/%s' % url.partition(get_script_prefix())[2]
try:
match = resolve(match_url)
except Resolver404:
pass
else:
current_url = '%s:%s' % (match.app_name, match.url_name)
changelist_url = 'admin:%s_%s_changelist' % (opts.app_label, opts.model_name)
if changelist_url == current_url and '_changelist_filters' in preserved_filters:
preserved_filters = dict(parse_qsl(preserved_filters['_changelist_filters']))
preserved_filters['dayofweek__exact'] = dayofweek
merged_qs.update(preserved_filters)
merged_qs.update(parsed_qs)
parsed_url[4] = urlencode(merged_qs)
return urlunparse(parsed_url)
然后在模板中我使用它:
{% lessonapp_preserved_filters adm_url '1' %}
答案 1 :(得分:0)
也许您尝试使用一些js解决方案。
只需使用js,构建字典从url获取所有当前属性。
单击其他属性按钮时,可以在字典中添加或替换属性。
答案 2 :(得分:0)
最后我解决了,尽管解决方案很冗长。
我想要一个多选过滤器,用户可以在其中过滤产品的品牌。 请注意,如果我每次单击多项选择字段时页面都刷新,就可以了。
我通过在视图中为过滤器中每个链接手动添加搜索参数,为多项选择中的每个字段构建了一个不同的链接。每次刷新页面时都会创建新链接,具体取决于选择的多项选择。
views.py 看起来像这样
from django.shortcuts import get_object_or_404, render
from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator
from .models import Product, Brand
from django.db.models import Q
def search(request):
queryset_list = Product.objects.order_by('price')
# Keyworks
if 'search' in request.GET:
search = request.GET['search']
if search:
queryset_list = queryset_list.filter(Q(name__icontains=search) | Q(description__icontains=search))
path = request.path
link = path + '?' + 'search=' + search
# Brands filter
brands_list = []
for query in queryset_list:
if query.brand.name not in brands_list:
brands_list.extend([query.brand.name])
brand_urls = {}
brand_active = [False] * len(brands_list)
if 'brand' not in request.GET:
for brand in brands_list:
brand_urls[brand] = link + '&' + 'brand=' + brand
else:
active_filters = [f for f in request.GET['brand'].split(',')]
if len(active_filters) > 1:
queryset_list = queryset_list.filter(brand__name__in=active_filters)
for k, brand in enumerate(brands_list):
new_active_filters = active_filters.copy()
if brand in new_active_filters:
brand_active[k] = True
new_active_filters.remove(brand)
brand_urls[brand] = link + '&' + 'brand=' + ','.join(new_active_filters)
else:
brand_active[k] = False
new_active_filters.append(brand)
brand_urls[brand] = link + '&' + 'brand=' + ','.join(new_active_filters)
paginator = Paginator(queryset_list, 12)
page = request.GET.get('page')
paged_products = paginator.get_page(page)
context = {
'products': paged_products,
'values': request.GET,
'brand_urls': brand_urls,
'brand_active': brand_active,
}
return render(request, 'products/search.html', context)
基本上,每个过滤器都是一个URL,其中包含查询参数。因此,我通过添加或删除参数为每个链接构建一个不同的URL,具体取决于该链接是否处于活动状态。
search.html 看起来像这样:
<h2>Brands</h2>
{% if brand_urls %}
<ol>
{% for brand in brand_urls.items %}
{% if brand_active|my_index:forloop.counter0 is True %}
<li><input type="checkbox" checked><a href="{{ brand.1 }}">{{ brand.0 }}</a></li>
{% else %}
<li><input type="checkbox"><a href="{{ brand.1 }}">{{ brand.0 }}</a></li>
{% endif %}
{% endfor %}
</ol>
{% endif %}
其中 my_index 是模板过滤器
from django import template
register = template.Library()
@register.filter
def my_index(List, i):
return List[int(i)]