繁体   English   中英

如何为 django 过滤器创建链接

[英]How to create link for django filter

设想:

产品可以在数据库中定义多个属性,我希望能够按这些属性进行过滤。

由于我还没有找到使用 django-filter 使用动态属性的方法,目前这是通过使用 django filter MethodFilter来实现的,该方法将作为查询字符串传递的属性解析为:

/products?attribute=size_2&attribute=color_red

像这样的 url 被解析并且可以工作。

问题是构建网址:

我找不到构建 url 的合理方法,它将考虑当前的搜索参数并添加/替换这些参数。

Django 似乎强迫我使用 urlconf 但 django-filter 使用查询字符串参数。

我试图实现的是:

用户位于页面/products?attribute=size_10 ,该页面显示具有该尺寸的所有产品。 当他点击“color red”链接时,新网址变为: /products?attribute=size_10&attribute=color_red

你能指出我实现这个的django方式吗?

如果在中间件中包含"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' %}

也许您尝试使用一些 js 解决方案。

  1. 只需使用 js 从 url 获取所有当前属性,构建 dict。

  2. 单击其他属性按钮时,您可以添加或替换字典中的属性。

  3. 使用此 dict 来形成您的网址。

最后我解决了,虽然解决方案很冗长。


语境

我想要一个多选过滤器,用户可以在其中过滤产品的品牌。 请注意,如果每次单击多选字段时页面都刷新,则可以。

大意

我通过在视图中为过滤器中的每个链接手动添加搜索参数,为多项选择中的每个字段构建一个不同的链接。 每次页面刷新时都会创建新链接,具体取决于选择了多项选择中的哪个选项。

代码

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM