如何在递归生成的<select>下拉列表上附加回调?

2024-05-17 00:02:36 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试实现链式相关下拉组合框选择,因此您首先选择一个组合框作为主类别,一旦选择主类别,另一个<select>将显示以选择子类别,依此类推,直到选择最内部(最具体)的类别。我目前的代码只适用于一个子类(直接子类),如何使它也适用于其他级别?因此,我需要以某种方式将onChange回调附加到新创建的<select>。你知道吗

这是我的Django模板中的jQuery代码:

{% extends 'pages/base.html' %}

{% block content %}
<h1>Create a product</h1>
<form method='POST' id='productForm' data-products-url="{% url 'products:ajax_load_categories' %}">
    {{ form.as_p }}
</form>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script>
    $("select").change(function () {
      var url = $("#productForm").attr("data-products-url");
      var categoryId = $(this).val();

      $.ajax({                       
        url: url,                    
        data: {
          'category': categoryId
        },
        success: function (data) {
          $("#productForm").append(data);
        }
      });
    });
</script>
{% endblock %}

以下是我的观点:

def load_categories(request):
    category_id = request.GET.get('category')
    subcategories = Category.objects.get(id=category_id).get_children()
    return render(request, 'products/category_dropdown_list_options.html', {'subcategories': subcategories})

products/category_dropdown_list_options.html

<select id="select_{{ subcategories.first.get_level }}">
    <option value="">---------</option>
    {% for subcategory in subcategories %}
        <option value="{{ subcategory.pk }}">{{ subcategory.name }}</option>
    {% endfor %}
</select>

这是我的网址.py地址:

app_name = 'products'
urlpatterns = [
    path('create/', product_create_view, name='product-create'),
    path('ajax/load-categories/', load_categories, name='ajax_load_categories')
]

以下是我根据要求提供的分类模型:

from mptt.models import MPTTModel, TreeForeignKey

class Category(MPTTModel):
    parent = TreeForeignKey('self', on_delete=models.CASCADE, null=True, blank=True, related_name='children')
    name = models.CharField(max_length=255)
    slug = models.SlugField()

    class Meta:
        unique_together = (('parent', 'slug',))
        verbose_name_plural = 'categories'

    class MPTTMeta:
        order_insertion_by = ['name']

    def __str__(self):
        return self.name

    def save(self, *args, **kwargs):
        self.slug = slugify(self.name)
        super().save(*args, **kwargs)

    def get_slug_list(self):
        ancestors = self.get_ancestors(include_self=True)
        slugs = [ancestor.slug for ancestor in ancestors]
        new_slugs = []
        for idx, ancestor in enumerate(slugs, 1):
            new_slugs.append('/'.join(slugs[:idx]))
        return new_slugs

    def get_recursive_product_count(self):
        return Product.objects.filter(category__in=self.get_descendants(include_self=True)).count()

Tags: nameselfidurldatagetdefload
1条回答
网友
1楼 · 发布于 2024-05-17 00:02:36

您需要将jQuery ajax脚本转换为函数,然后递归调用它,如下所示:

<script>
    var $r_ = function() {
        var url = $("#productForm").attr("data-products-url");
        var categoryId = $(this).val();
        $.ajax({                       
          url: url,                    
          data: {
            'category': categoryId
          },
          success: function (data) {
            if (data != 'leaf_node') {
              $("#productForm").append(data);
            }
            $('select').change($r_);
          }
        });

    } //end of $r_

    $('select').change($r_);
</script>

更新

如果您查看MPTT模型的get_children方法,您将看到它检查实例是否有任何子对象,如果没有,则返回None

在视图中添加None检查,然后在到达叶节点时添加不同的响应:

from django.http import HttpResponse

def load_categories(request):
    category_id = request.GET.get('category')
    subcategories = Category.objects.get(id=category_id).get_children()
    if subcategories:
        return render(request, 'products/category_dropdown_list_options.html', {'subcategories': subcategories})

    return HttpResponse('leaf_node')

然后在ajax调用中添加对叶节点的检查(见上文)。你知道吗

相关问题 更多 >