Quiero tener un formulario de texto simple en cada fila de una tabla.
Ilustración de violín del resultado esperado: https://jsfiddle.net/wstg759f/1/
Mis Models.py :
class Person(models.Model): name = models.CharField(max_length=30) class Quality(models.Model): name = models.CharField(max_length=30) person=models.ForeignKey(Person)Tengo un conjunto de consultas que devuelve una lista agregada de todas las personas, el recuento de cualidades de cada persona, una cualidad aleatoria de esta persona:
[ {'the_count': 5, u'randomquality': u'Nice', u'person__name': u'Joe'}, {'the_count': 4, u'randomquality': u'Generous',u'person__name': u'Mike'}, {'the_count': 4, u'randomquality': u'Healthy',u'person__name': u'John''}, .. ]Mi view.html (las cualidades son mi conjunto de consultas)
<table> <thead> <tr> <th>Person</th> <th>Qualities count</th> <th>One random quality</th> <th>Add a Quality?</th> </tr> </thead> <tbody> {%for obj in qualities%} <tr> <td>{{ obj.person__name }}</td> <td>{{ obj.the_count }}</td> <td>{{ obj.randomquality }}</td> <td>text form to submit a quality for this person</td> </tr> {% endfor %} </tbody> </table>El usuario debe poder ingresar una calidad en el campo de texto y, una vez enviado, se agregará al modelo y el campo de texto se reemplazará por "gracias, enviado". El formulario de envío debe ser independiente. No tengo una dirección clara hacia dónde mirar. ¿Cómo harías?
De mi lectura, entiendo que formset podría ser una solución, pero no me queda claro. ¿Debería incluso usar el formulario django en este caso? En caso afirmativo, creo que el formulario debe tomar un argumento de la plantilla: no necesito que el usuario me informe sobre el nombre de la persona, ya que ya está aquí. Déjame saber si puedo aclarar. Gracias por adelantado.
Como beneficio adicional, tal vez para más adelante, quiero evitar la actualización de la página. ¿Ajax es la única manera?
Puedes hacer esto con ajax, formulario y vistas.
plantilla.html
<table> <thead> <tr> <th>Person</th> <th>Qualities count</th> <th>One random quality</th> <th>Add a Quality?</th> <th>Button</th> </tr> </thead> <tbody> {% for obj in qualities %} <tr id="row_{{ obj.id }}"> <td>{{ obj.person__name }}</td> <td>{{ obj.the_count }}</td> <td>{{ obj.randomquality }}</td> <td>{{ form.quality }}</td> <td><button value="{{ obj.id }}" onclick="addQuality(this.value)">Add</button></td> </tr> {% endfor %} </tbody> </table> <script> function addQuality(id_object) { const csrftoken = document.querySelector('[name=csrfmiddlewaretoken]').value let data_to_backend = new FormData() let qualityToAdd = document.getElementById(`id_${id_object}-quality`).value if (qualityToAdd !== '') { data_to_backend.append('quality', qualityToAdd) data_to_backend.append('object_index', id_object) } else return const request = new Request("./", { method: 'POST', headers: {'X-CSRFToken': csrftoken}, body: data_to_backend }) fetch(request, { method: 'POST', mode: 'same-origin' }).then( function(response) { if (response.status === 200) { let tableRow = document.getElementById(`row_${ id_object }`) tableRow.innerHTML = "<p>thanks, submitted</p>" } else { alert("Error") console.log(response) } } ) } </script>Configure sus vistas para recibir una solicitud de publicación o simplemente cree una nueva ruta de URL y otras vistas
vistas.py
def addQuantity(request, codigo_orcamento): if request.method == "POST": form = formAddQuantity(request.POST) if form.is_valid(): id_object = form.cleaned_data['object_index'] quality = form.cleaned_data['quality'] # get the object and add this quality return HttpResponse(status=200) else: return HttpResponse(status=400) else: return HttpResponse(status=405)En esta vista, simplemente verificamos si el formulario es válido, obtenemos el objeto de db y le agregamos la calidad
formularios.py
class formAddQuantity(forms.Form): object_index = forms.IntegerField(min_value=0) quality = forms.CharField(max_length=100)Una verificación simple, pero le recomiendo que agregue más requisitos a estos campos
(No probado, si arroja un error avísame)