Обслуживание другой ModelForm на основе выбранной категории - PullRequest
0 голосов
/ 01 октября 2019

Я создаю страницу для добавления товаров в интернет-магазин пользователем, и я сделал цепочечный зависимый выбор комбинированного списка, где вы начинаете с одного комбинированного списка для основной категории продуктов, а после выбора основной категории появляется другая <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.

Я не уверен, стоит ли вообще идти этим путем, любой вход приветствуется.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...