Как создать экземпляр модели из формы с полями 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}
Любой вид руководства будет оценен по достоинству, спасибо за прочтение, любая дополнительная информация или редактирование необходимы, просто скажите мне, я буду рад сделать это.