如何在 Django 中使用 Ajax 对列表视图进行排序?

Posted

技术标签:

【中文标题】如何在 Django 中使用 Ajax 对列表视图进行排序?【英文标题】:How to sort list view using Ajax in Django? 【发布时间】:2020-10-07 07:46:00 【问题描述】:

在列表视图模板中,我创建了一个过滤器表单来过滤帖子,它们也是一个排序下拉列表来对它们进行排序:

<form id="sortForm">
    <select class="input-text" id="sort" onchange="document.querySelector('#sortSubmitBtn').click()" name="sort"
        id="sort">
        <option disabled selected>Sort by</option>
        <option value="price_l2h" % if 'price_l2h' == values.sort % selected % endif %>
            Price (low to high)</option>
        <option value="price_h2l" % if 'price_h2l' == values.sort % selected % endif %>
            Price (high to low)</option>
    </select>
    % if values.keywords %
    <input type="hidden" name="keywords" id="keywords" value=" values.keywords ">
    % endif %
    % if values.mls_number %
    <input type="hidden" name="mls_number" id="mls_number" value=" values.mls_number ">
    % endif %

    <button type="submit" id="sortSubmitBtn" style="display: none;">Submit</button>
</form>

这是我用来排序的 Ajax,但它不起作用。我使用相同的 Ajax 语法在模型中保存数据,它工作得很好,但是这个不起作用。

<script>
    $(document).on('submit', '#sortForm', function (e) 
        e.preventDefault();

        $.ajax(
            type: 'GET',
            url: "% url 'listing:search' %",
            data: 
                sort: $('#sort').val(),
                keywords: $('#keywords').val(),
                mls_number: $('#mls_number').val(),
                csrfmiddlewaretoken: " csrf_token ",
            ,
            success: function () 
                alert('Form submitted successfully!!');
            
        )
    )

</script>

urls.py:

path('search/', search, name='search'),

谢谢你,我希望有人能帮我解决这个问题。

编辑:这是 GUI 的外观,选择时我希望它对列表进行排序:

编辑:views.py 添加了

def search(request):
    queryset = Listing.objects.all().order_by('listing_date')

    listing_for = request.GET.get('listing_for')

    # filter by price
    min_price = request.GET.get('min_price')
    max_price = request.GET.get('max_price')
    if min_price and max_price:
        queryset = queryset.filter(price__range=(min_price, max_price))

    # Filter by new mls number
    mls_number = request.GET.get('mls_number')
    if mls_number:
        queryset = queryset.filter(mls_number__exact=mls_number)

    # filter by keyword
    keywords = request.GET.get('keywords')
    if keywords:
        queryset = queryset.filter(Q(description__icontains=keywords) | Q(
            lot_feature__title__icontains=keywords) | Q(interior_feature__title__icontains=keywords) | Q(exterior_finish__title__icontains=keywords) | Q(extra_feature__title__icontains=keywords) | Q(appliances__title__icontains=keywords) | Q(view__title__icontains=keywords)).distinct()

    # sorting function
    sort_by = request.GET.get('sort')
    if sort_by:
        if sort_by == 'price_l2h':
            queryset = queryset.order_by('price')
        elif sort_by == 'price_h2l':
            queryset = queryset.order_by('-price')
        elif sort_by == 'newest':
            queryset = queryset.order_by('-listing_date')
        elif sort_by == 'bedrooms':
            queryset = queryset.order_by('-bedrooms')
        elif sort_by == 'bathrooms':
            queryset = queryset.order_by('-bathrooms')
        elif sort_by == 'sqrft':
            queryset = queryset.order_by('-sqrft')

    context = 
        'listings': queryset,
        'city': city,
        'provinces': provinces,
        'prices': prices,
        'property_types': property_type,
        'rooms': rooms,
        'values': request.GET,
        'int_values': int_values,
        'page': page,
    

    return render(request, 'listing/listings.html', context)

【问题讨论】:

有什么错误吗?您也可以添加您的视图,它是如何不起作用的? 没有错误,列表按预期过滤,但我不希望刷新页面,因为我使用的是 Ajax。为什么 Ajax 在这里不起作用 【参考方案1】:

假设您有下表:

<select name="orderby" class="form-control" id="sort">
                                            <option value="default" selected="selected">Default sorting</option>
                                            <option value="rating" name ="rating">Sort by average rating</option>
                                            <option value="date" name ="date">Sort by latest</option>
                                            <option value="price-low" name ="price-low">Sort by price: low to high</option>
                                            <option value="price-high" name ="price-high">Sort by price: high to low</option>
                                        </select>

我们从 select 中选择 id 属性并从 Ajax 中提取数据值。

$(document).ready(function()
    $('#sort').on('change', function() 
        var sortid = $('#sort').val();

        $.ajax(
            type: 'POST',
            url: $(this).data('url'),
            datatype: 'json',
            data: 'sortid': sortid
        ).done(function (data) 
            $('.product-wrapper').html(data.sort_by_choice);
        );
    );

    



这里,当#sort id 的值改变时,我们将该值分配给变量sortid。

我们正在通过 Ajax 将数据传递到服务器。

我用过POST方法,如果我们不定义方法,默认方法是GET。我正在分配当前 URL,我们也只能分配直接 URL。例如:网址:shop/,

我们的数据类型是JSON,数据是从变量中获取的数据。

现在让我们在下面创建我们的views.py:

def products(request):
    
    products = Products.objects.all().order_by('created_at')
    if request.is_ajax() or request.method == 'POST':
        sort_parameter = request.POST.get('sortid')
    
        if sort_parameter == 'price-high':
            products = products.order_by('price')
        elif sort_parameter == 'price-low':
            products = products.order_by('-price')
        elif sort_parameter == 'date':
            products = products.order_by('-created_at')
        
        
        products = render_to_string(
            template_name="shop.html", 
           context = 
                    'products': products,
             
        )

        json_sort = "sort_by_choice": products
        return JsonResponse(data=json_sort, safe=False)
            
    return render(request, 'ecommerce/shop.html', 'products': products)
    

这里如果请求是 ajax,我从 POST get 方法中获取 sort_parameter。如果您在 javascript 文件中的类型是 GET,则我的帖子类型是 POST,您需要通过 GET 方法获取。

之后,

我已经循环排序参数并将参数呈现为字符串。我们需要 render_to_string 因为它会加载一个模板并立即调用它的 render() 方法。

在此之后,我们需要为 AJAX 请求返回 JsonResponse。

如果请求不是 AJAX,则返回常规响应。

加载 JsonResponse 和 render_to_string 导入:

from django.template.loader import render_to_string
from django.http import JsonResponse

【讨论】:

【参考方案2】:

ajax 不是这样工作的,你需要发送一个 JsonResponse 并操作它。对于这种操作,您可以使用django-rest-framework,这将使您的工作更简单。如果您不想使用它,则必须修改类似于此的代码 link.

【讨论】:

【参考方案3】:

要在服务器端对数据进行排序,您可以使用 QuerySet 的 order_by-method 或 Model 的 ordering-Meta-option。

您还可以在客户端用 JavaScript 对返回的数据进行排序。

【讨论】:

我知道如何排序,功能正常。这里怎么应用Ajax,为什么Ajax不行? @ytsejam 说你需要发送一个 JsonResponse。 this answer 很好地解释了如何做到这一点。

以上是关于如何在 Django 中使用 Ajax 对列表视图进行排序?的主要内容,如果未能解决你的问题,请参考以下文章

通过jQuery ajax调用将值列表传递给django视图

如何通过 ajax 将值从 django 模板发送到视图?

Django & Ajax - 没有返回语句的视图

如何在django中使用类似AJAX的视图?

如何在 Django 视图中使用 ajax POST 解析 json 数据

Django - 如何正确地将列表从模板发送到 AJAX 以查看?