Или нет…
Продолжаю бороться с этими формами((На одной странице есть 2 формы.
Есть 2 модели: 1. Product. 2. SpeciallyPrice. SpeciallyPrice связан через FK с Product. В то же время, SpecialPrice является InlineModel в Product.
Поля формы SpecialPriceForm автоматически создаются суриптом JS. То есть их может быть n-ное колличествоо. Необходимо создать запись для каждого такого срабатывания скрипта. В принципе, я догадываюсь, как это сделать - использовать цикл для списка полученных значений. Но проблема в том, что я не могу получить этот список. По какой-то причине из формы приходит None.
 class ProductsCreate(CreateView):
    model = Product
    form_class = ProductCreateForm
    http_method_names = ['get', 'post']
    def get_initial(self):
        initial = super(ProductsCreate, self).get_initial()
        initial['request'] = self.request
        return initial
    def get_context_data(self, *args, **kwargs):
        ctx=super(ProductsCreate, self).get_context_data(*args, **kwargs)
        ctx['special_form'] = SpeciallyPriceForm()
        return ctx
    def get(self, request, *args, **kwargs):
        self.object = None
        if kwargs.get('slug'):
            category = Category.objects.filter(slug=kwargs.get('slug')).first()
            self.initial.update({'category': category})
        return self.render_to_response(self.get_context_data())
    def post(self, request, *args, **kwargs):
        self.object = None
        form = ProductCreateForm(request.POST, request.FILES, initial={'request': request})
        special_form = SpeciallyPriceForm(request.POST)
        print(special_form)                            #Пустая форма, но валидна. Как?
        if form.is_valid() and special_form.is_valid():
            return self.form_valid(form, special_form)
        else:
            return self.form_invalid(form, special_form)
    def form_valid(self, form, special_form):
        product = form.save(commit=False)
        product.user = self.request.user
        product.save()
        for cat in form.cleaned_data.get('category'):
            product.category.add(cat)
        for paym in form.cleaned_data.get('payment_method'):
            product.payment_method.add(paym)
        for distr in form.cleaned_data.get('distribution_type'):
            product.distribution_type.add(distr)
        
        #Здесь я думал под каждый элемент списка создавать запись, связанную с созданным продуктом. Верна ли логика?
        special = special_form.save(commit=False)
        special.product = product
        special.save()
        for spec_price in special_form.cleaned_data.get('adittional_specially_price'):
            print(spec_price)
            special.adittional_specially_price = spec_price
        for spec_numb in special_form.cleaned_data.get('adittional_specially_number'):
            print(spec_numb)
            special.adittional_specially_number = spec_numb
 class ProductCreateForm(forms.ModelForm):
    #...
class SpeciallyPriceForm(forms.ModelForm): 
    class Meta: 
        model = SpeciallyPrice 
        fields = ['adittional_specially_price', 'adittional_specially_number']
    def clean(self):
        cleaned_data = super(SpeciallyPriceForm, self).clean()
        cd_adittional_specially_price = cleaned_data.get('adittional_specially_price')
        print(cd_adittional_specially_price)   #None
        cd_adittional_specially_number = cleaned_data.get('adittional_specially_number')
        print(cd_adittional_specially_number)  #None
Шаблон Джанго + скрипт
 <html><body>
Special price from {{ special_form.adittional_specially_price }} kg {{ special_form.adittional_specially_number }} usd
    <script>
        (function(){
            var copy = document.querySelector('.field.inline.specially').cloneNode(true);
            document.querySelector('html').addEventListener('input', function(e){
                if(e.target.classList.contains('event') && e.target.tagName == 'INPUT'){
                    var error = 0;
                    for(var evt of document.querySelectorAll('.field.inline.specially input.event')){
                        evt.value = evt.value.replace(/[^\d]/,'');
                        if(!evt.value || +evt.value < 1) error++;
                    }
                    if(!error){
                        var last = document.querySelectorAll('.field.inline.specially');
                        last[last.length-1].insertAdjacentHTML('afterEnd', copy.outerHTML);
                    }
                }
            });
        })();
    </script>
</body></html>
Когда я пытался посмотреть во views эту форму, получал просто пустаю форму вроде этой. Но почему она валидна, Карл?
 <label for="specially" class="subhead">Special price from</label>
<span class="id_specially_price"><input type="text" name="adittional_specially_price" style="width: 165px" class="event" id="id_adittional_specially_price"></span>
<span>kg</span>
<span class="id_specially_number"><input type="text" name="adittional_specially_number" style="width: 100px" class="event" id="id_adittional_specially_number"></span>
<span>usd</span>
Может быть, это нужно решать через Ajax, как-то обрабатывать запрос? Или есть какой-то “джанговский” способ?
Как вариант, я думаю, что во views показны только последние два поля, которые остаются пустыми. Но в этом я не уверен. Я тут, кстати, ещё заметил, что айдишник у созданных полей у инпутов повторяются. Возможно, в этом и есть баг…