Как создать экземпляр модели из формы с полями AJAX в Django?

I'm having troubles to create a model instance using a template that use AJAX to have a chained dropdown (I had followed this to do that functionality). When I want to save the form, my CreateView returns "form is invalid" and I don't know where is the problem. The commented blocks inside views.py are the methods that I investigated to solve the problem but couldn't figured out how. I suspect that my form does not load correctly my post data and could not retrieve the proper objects to save the instance for my model. Here is what I have until now:
models.py:

import uuid
from django.db import models
from django.forms import ModelForm, Textarea, RadioSelect, Select

# Create your models here.
class Cliente(models.Model):
    nombre = models.CharField("Nombre", max_length=50)
    descripcion = models.CharField("Descripción", max_length=120)
    def __str__(self):
        return '%s' % (self.nombre)

class Servicio(models.Model):
    nombre = models.CharField("Nombre", max_length=50)
    descripcion = models.CharField("Descripción", max_length=120)
    clientes = models.ManyToManyField(Cliente, verbose_name="Clientes")
    def __str__(self):
        return '%s' % (self.nombre)

class Etiqueta(models.Model):
    nombre = models.CharField(max_length=50)
    descripcion = models.CharField(max_length=120)
    servicios = models.ManyToManyField(Servicio, verbose_name="Servicios")
    def __str__(self):
        return '%s' % (self.nombre)
# This is the model that I could not create new instances for my model
class Lote(models.Model):
    lote_id = models.UUIDField(primary_key=False, default=uuid.uuid4, editable=False)
    creacion = models.DateTimeField(auto_now=False, auto_now_add=True)
    modificacion = models.DateTimeField(auto_now=True)
    cliente = models.ManyToManyField(Cliente, verbose_name="Cliente")
    servicio = models.ManyToManyField(Servicio, verbose_name="Servicio")
    etiqueta = models.ManyToManyField(Etiqueta, verbose_name="Etiqueta")

class Archivo(models.Model):
    lote = models.ForeignKey('Lote', on_delete=models.CASCADE)
    archivo = models.FileField(upload_to='uploads/%Y/%m/%d/')

forms.py:

from django.forms import ModelForm, Select
from crea_lote.models import Lote, Servicio, Etiqueta

class LoteForm(ModelForm):
    class Meta:
        model = Lote
        fields = ('cliente', 'servicio', 'etiqueta')
        widgets = {'cliente': Select, 'servicio': Select, 'etiqueta': Select}

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['servicio'].queryset = Servicio.objects.none()
        self.fields['etiqueta'].queryset = Etiqueta.objects.none()

views.py:

from crea_lote.models import Lote, Cliente, Servicio, Etiqueta
from crea_lote.forms import LoteForm


# Create your views here.
class IndexView(TemplateView):
    template_name = "crea_lote/index.html"


class LoteCreate(CreateView):
    model = Lote
    form_class = LoteForm
    success_url = reverse_lazy('lote_list_view')
"""  
    def get_form_kwargs(self):
        kwargs = super().get_form_kwargs()
        print(kwargs)
        if hasattr(self, 'object'):  
            kwargs.update({'instance':self.object})
        return kwargs
"""
"""
    def form_valid(self, form):
        self.object = form.save()
        print(form.instance)
        return super().form_valid(form)
""" 
class LoteListView(ListView):
    model = Lote
    context_object_name = 'lotes'

class LoteUpdateView(UpdateView):
    model = Lote
    fields = ('cliente','servicio','etiqueta')
    success_url = reverse_lazy('lote_list_view')

def load_servicios(request):
    cliente_id = request.GET.get('cliente')
    servicios = Servicio.objects.filter(clientes__id=cliente_id)
    response = TemplateResponse(request, 'crea_lote/servicios_list.html', {'servicios': servicios})
    return response


def load_etiquetas(request):
    servicio_id = request.GET.get('servicio')
    etiquetas = Etiqueta.objects.filter(servicios__id=servicio_id)
    response = TemplateResponse(request, 'crea_lote/etiquetas_list.html', {'etiquetas': etiquetas})
    return response

Мой шаблон (lote_form.html):

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Crear Lote</title>
</head>
<body>
    <h1>Crear Lote form</h1>
    <!-- "{% url 'salida-form-lote' %}" -->
    <!-- action="{% url 'salida-form-lote' %}" -->
<form method="post" id="lote-form" data-servicios-url="{% url 'ajax_load_servicios' %}" data-etiquetas-url="{% url 'ajax_load_etiquetas' %}">
    {% csrf_token %}
    <table>
        {{ form.as_table }}
    </table>
    <input type="submit" value="Save">
</form>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script>
    $('#id_cliente').change(function(){
        // console.log("dentro de function");
        var url = $("#lote-form").attr("data-servicios-url");
        console.log("url: " + toString(url));
        var clienteId = $(this).val();
        //console.log("ClienteId: " + clienteId);

        $.ajax({
            url: url,
            data: {
                'cliente': clienteId
            },
            success: function(data){
                $('#id_servicio').html(data);
            }
        });
    });

        $('#id_servicio').change(function(){
        console.log("dentro de function etiquetas");
        var url = $("#lote-form").attr("data-etiquetas-url");
        var servicioId = $(this).val();
        $.ajax({
            url: url,
            data: {
                'servicio': servicioId
            },
            success: function(data){
                $('#id_etiqueta').html(data);
            }
        });
    });
</script>
</body>
</html>

Здесь приведен результат print(kwargs):

{'initial': {}, 'prefix': None, 'data': <QueryDict: {'csrfmiddlewaretoken': ['FWbHCYgtPnLybUVCaqRddJo1n7z5ZYwpS9Yj5xRasY5lgbul6nefqYm9i8f6G5tn'], 'cliente': ['1'], 'servicio': ['1'], 'etiqueta': ['1']}>, 'files': <MultiValueDict: {}>, 'instance': None}

Here are my outputs:
form_rendered_ok
form_invalid

Любой вид руководства будет оценен по достоинству, спасибо за прочтение, любая дополнительная информация или редактирование необходимы, просто скажите мне, я буду рад сделать это.

Вернуться на верх