[ clydefrog @ 01.10.2019. 14:06 ] @
Pravim stranicu za dodavanje proizvoda u webshop od strane korisnika, i napravio sam 'chained dependent combobox selection', gde se počinje od jednog combobox-a za glavnu kategoriju, i kada se selektuje glavna kategorija, pojavljuje se još jedan <select> za selektovanje potkategorije, i tako dalje sve dok se ne odabere najspecifičnija, najuža kategorija. Ovo trenutno radi na sledeći način: kad god se vrednost u combobox-u promeni, šalju se dva AJAX requesta. Prvi poziva view koji renderuje sledeći <select> ako kategorija ima 'dece', u suprotnom vraća HttpResponse koji prestaje da kači listener. Drugi request poziva view koji renderuje poseban, drugi ModelForm ako je selektovana kategorija root node (glavna kategorija), u suprotnom vraća HttpResponse koji kaže da se ne renderuje drugi ModelForm Pokušavam da serviram posebni ModelForm baziran na selektovanoj glavnoj kategoriji. Na primer, ako postoje dve glavne kategorije, Books i Shoes, ako selektuješ Books, BookModelForm treba da se pojavi i proizvod treba biti sačuvan kao Book. Implementirao sam taj deo oko serviranja drugog ModelForm-a, ali problem je sam product_create_view i snimanje proizvoda u bazu. views.py: Code: mappings = { '1': BookProductForm, '2': ShoesProductForm } def load_categories(request): category_id = request.GET.get('category') request.session['category'] = category_id 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') def load_modelform(request): category = request.GET.get('category') form = mappings[category] if Category.objects.get(id=int(category)).is_root_node(): return render(request, 'products/category_modelform.html', {'form': form}) return HttpResponse('dont_change_modelform') @login_required def product_create_view(request): if request.method == 'POST': create_product_form = CreateProductForm(request.POST, request=request) if create_product_form.is_valid(): create_product_form.save() else: create_product_form = CreateProductForm(request=request) return render(request, 'products/product_create.html', {'form': create_product_form}) forms.py: Code: from django import forms from django.forms import ModelForm from .models import Product, Category, Book, Shoes class CreateProductForm(ModelForm): class Meta: model = Product fields = ( 'title', 'description', 'price', 'stock', 'category' ) def __init__(self, *args, **kwargs): self.request = kwargs.pop('request') super().__init__(*args, **kwargs) self.fields['category'].queryset = Category.objects.filter(parent=None) def clean_category(self): category = Category.objects.get(id=self.request.session.get('category')) if category.is_leaf_node(): return category else: raise forms.ValidationError('Please select the most specific category.') class BookProductForm(ModelForm): class Meta: model = Book fields = ( 'title', 'description', 'price', 'stock', 'author', 'publisher', 'language', 'year', 'isbn' ) class ShoesProductForm(ModelForm): class Meta: model = Shoes fields = ( 'title', 'description', 'price', 'stock', 'size', 'colour' ) Template: Code: <h1>Create a product</h1> <div class='modelform'> <form method='POST' id='productForm' data-products-url="{% url 'products:ajax_load_categories' %}" data-modelform-url="{% url 'products:ajax_load_modelform' %}"> {% csrf_token %} <div class='the-rest'> {{ form.non_field_errors }} {% for field in form %} {% ifnotequal field.name 'category' %} {{ field.label_tag }} {{ field }} {{ field.errors }} {% endifnotequal %} {% endfor %} </div> <div class='categories'> {{ form.category.label_tag }} {{ form.category }} </div> <input type="submit" name="" value="Submit"> </form> </div> <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(); $(".categories").append(data); } else { toRemove.remove(); } } }); var url2 = $('#productForm').attr('data-modelform-url'); $.ajax({ url: url2, data: { 'category': categoryId }, success: function (data) { if (data != 'dont_change_modelform') { $('.the-rest').empty(); $('.the-rest').append(data); } } }); } $(document).on('change', 'select', $r_); </script> Pokušao sam ovo da rešim postojanjem samo jedne forme, CreateProductForm, kojoj bi prosledio model, ali sam došao u situaciju gde treba da dohvatim CreateProductForm klasu iz unutrašnje Meta klase. Nisam siguran da je ovo pravo rešenje na prvom mestu, saveti dobrodošli. |