Я создаю страницу для добавления товаров в интернет-магазин пользователем, и я сделал цепочечный зависимый выбор комбинированного списка, где вы начинаете с одного комбинированного списка для основной категории продуктов, а после выбора основной категории появляется другая <select>
для выбора подкатегории и т. д., пока не будет выбрана самая внутренняя (наиболее конкретная) подкатегория.
В настоящее время это работает следующим образом: всякий раз, когда значение в комбинированном ящике изменяется, запускаются два запроса AJAX. Сначала вызывается представление, которое отображает другое <select>
, если у категории есть дочерние элементы, в противном случае возвращается HttpResponse, который прекращает присоединение слушателя. Второй вызывает представление, которое отображает другую ModelForm, если выбранная категория является корневым узлом (основная категория), в противном случае возвращает HttpResponse, который говорит, что не следует отображать другую ModelForm.
Я хочу обслуживать другую ModelForm на основе выбранной главнойкатегория. Так, скажем, если есть две основные категории, «Книги» и «Обувь», если вы выберете «Книги», должно появиться BookModelForm и продукт должен быть сохранен как книга. Я выполняю другую часть ModelForm, но проблема заключается в product_create_view
и сохранении продукта в базе данных.
Это мой views.py
:
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
:
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'
)
... и вот мой шаблон:
<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>
Я попытался сохранить только одну форму, CreateProductForm, и передать ей модель, однако яЯ попал в ситуацию, когда мне нужно было получить доступ к классу CreateProductForm из класса Meta.
Я не уверен, стоит ли вообще идти этим путем, любой вход приветствуется.