[ clydefrog @ 30.09.2019. 16:01 ] @
Implementujem 'chained dependent combobox selection', dakle počinje se sa jednim combobox-om za glavnu kategoriju, i kada se selektuje glavna kategorija, pojavljuje se još jedan <select> za selektovanje potkategorije, i tako dalje sve dok se najspecifičnija, najuža kategorija ne izabere. Ovo trenutno radi ovako: kad god se vrednost u combobox-u promeni, šalje se AJAX request koji poziva view koji renderuje još jedan <select> ako kategorija ima 'dece', u suprotnom vraća HttpResponse koji prestaje da 'kači' listener. Koristim django-mptt da modelujem svoje kategorije. Dakle, imam jedan view za dodavanje proizvoda i hoću da budem siguran da je najuža kategorija (mora da bude leaf node) selektovana i da dodelim tu kategoriju svojoj Product instanci. Evo ga taj view: Code: @login_required def product_create_view(request): if request.method == 'POST': create_product_form = CreateProductForm(request.POST) else: create_product_form = CreateProductForm() return render(request, 'products/product_create.html', {'form': create_product_form}) Evo je forma: Code: from django.forms import ModelForm from .models import Product, Category class CreateProductForm(ModelForm): class Meta: model = Product fields = ( 'title', 'description', 'price', 'year', 'category', ) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.fields['category'].queryset = Category.objects.filter(parent=None) products/product_create.html: Code: {% extends 'pages/base.html' %} {% block content %} <h1>Create a product</h1> <form method='POST' id='productForm' data-products-url="{% url 'products:ajax_load_categories' %}"> <label>Title</label> {{ form.title }} <label>Description</label> {{ form.description }} <label>Price</label> {{ form.price }} <label>Year</label> {{ form.year }} <label>Category</label> {{ form.category }} </form> <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script> <script> var $r_ = function() { var url = $("#productForm").attr("data-products-url"); var categoryId = $(this).val(); var toRemove = $(this).nextAll('select'); $.ajax({ url: url, data: { 'category': categoryId }, success: function (data) { if (data != 'leaf_node') { toRemove.remove(); $("#productForm").append(data); } else { toRemove.remove(); } } }); } //end of $r_ $(document).on('change', 'select', $r_); </script> {% endblock %} Ovo je ajax_load_categories view: Code: 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') products/category_dropdown_list_options.html: Code: <select> <option value="">---------</option> {% for subcategory in subcategories %} <option value="{{ subcategory.pk }}">{{ subcategory.name }}</option> {% endfor %} </select> I za svaki slučaju Category model: Code: 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() |