Страница с динамическим количеством форм, каждая форма для каждой строки таблицы
В компании есть работники, выполняющие различные виды деятельности в течение дня. У каждого вида деятельности есть start_time
и finish_time
. Обычно работники забывают подать звуковой сигнал об окончании деятельности (finish_time
), и это потому, что существует хранимая процедура read_unended time_from time_to
, которая считывает записи между time_from
и time_to
, в которых нет finish_time
(есть NULL
).
Например
id name day start_time finish_time place activity
38 Thomas 2021-12-03 2021-12-03 08:51:38.000 NULL p1 a1
28 Charles 2021-12-02 2021-12-02 12:29:03.000 NULL p2 a2
49 John 2021-12-06 2021-12-06 11:59:48.000 NULL p3 a3
68 Jessie 2021-12-08 2021-12-08 10:55:12.000 NULL p4 a4
82 Susanne 2021-12-10 2021-12-10 12:38:03.000 NULL p5 a5
Существует форма в (forms.py
)
class FromToForm(Form):
start_date = DateField(widget=AdminDateWidget())
start_time = TimeField(widget=AdminTimeWidget())
end_date = DateField(widget=AdminDateWidget())
end_time = TimeField(widget=AdminTimeWidget())
Существует представление в (views.py
), которое отображает такую таблицу.
def ending(req):
from_to_form = FromToForm()
result = []
context = {
'form': from_to_form,
'result': result
}
if req.method == "POST":
from_to_form = FromToForm(req.POST)
if from_to_form.is_valid():
start = datetime.combine(from_to_form.cleaned_data['start_date'], from_to_form.cleaned_data['start_time']).isoformat()
end = datetime.combine(from_to_form.cleaned_data['end_date'], from_to_form.cleaned_data['end_time']).isoformat()
with connections["mssql_database"].cursor() as cursor:
cursor.execute("EXEC read_unended @dt_od='%s', @dt_do='%s'" % (start, end))
result = cursor.fetchall()
context['result'] = result
return render(req, 'ending.html', context)
else:
return render(req, 'ending.html', context)
else:
return render(req, 'ending.html', context)
и связанный с ним шаблон в templates.py
.
<form action='.' method='POST'>{% csrf_token %}
{{ form.media }}
{{ form.as_p }}
<input type='submit' value='Read unended' class="btn btn-secondary" />
</form>
{% if result %}
<table class="table mb-0">
<thead>
<tr>
<th>id</th>
<th>name</th>
<th>day</th>
<th>start_time</th>
<th>finish_time</th>
<th>place</th>
<th>activity</th>
</tr>
</thead>
<tbody>
{%for i in result %}
<tr>
<td>{{i.0}}</td>
<td>{{i.1}}</td>
<td>{{i.2}}</td>
<td>{{i.3}}</td>
<td>CELL TO INSERT END TIME*</td>
<td>{{i.5}}</td>
<td>{{i.6}}</td>
<td>BUTTON TO FINISH THIS ACTIVITY**<td/>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
Every activity is ended
{% endif %}
** и * пока не реализованы.
Я хотел бы реализовать следующую функциональность. В каждой строке динамически генерируемой таблицы должна быть кнопка ** для завершения этой активности (этой строки) со временем * вставки пользователем приложения. В этот момент страница должна обновиться и эта строка больше не должна отображаться, так как эта активность уже finish_time
назначена. Как я могу реализовать такое представление и шаблон? Нужно ли мне добавить динамически генерируемые поля в существующую форму? Что вы посоветуете?
Вам нужно создать функцию для отправки данных и другую для получения тела таблицы
template.html
<table class="table mb-0">
<thead>
<tr>
<th>id</th>
<th>name</th>
<th>day</th>
<th>start_time</th>
<th>finish_time</th>
<th>place</th>
<th>activity</th>
</tr>
</thead>
<tbody id="tbodyId">
{% for i in result %}
<tr>
<td id="tdId_{{ i.id }}0">{{i.0}}</td>
<td id="tdId_{{ i.id }}1">{{i.1}}</td>
<td id="tdId_{{ i.id }}2">{{i.2}}</td>
<td id="tdId_{{ i.id }}3">{{i.3}}</td>
<td id="tdId_{{ i.id }}4">CELL TO INSERT END TIME*</td>
<td id="tdId_{{ i.id }}5">{{i.5}}</td>
<td id="tdId_{{ i.id }}6">{{i.6}}</td>
<td><button value="{{i.id}}" type="button" onclick="setEndActivity(this.value)">End</button><td/>
</tr>
{% endfor %}
</tbody>
</table>
<script>
function loadResults() {
let xhttpRequest = new XMLHttpRequest()
xhttpRequest.onreadystatechange = function (data) {
if (this.readyState === 4 && this.status === 200) {
document.getElementById("tbodyId").innerHTML = this.response
}
}
xhttpRequest.open("GET", "./ajax/load-results/", true)
xhttpRequest.send()
}
function setEndActivity(activityId) {
const dataToBackEnd = new FormData()
dataToBackEnd.append("activity", activityId)
dataToBackEnd.append("start_date", document.getElementById(`tdId_${i.id}2`).value)
dataToBackEnd.append("start_time", document.getElementById(`tdId_${i.id}2`).value)
dataToBackEnd.append("end_date", document.getElementById(`tdId_${i.id}2`).value)
dataToBackEnd.append("end_time", document.getElementById(`tdId_${i.id}2`).value)
const request = new Request('./ajax/end-activity/',
{
method: 'POST',
headers: { 'X-CSRFToken': document.querySelector('[name=csrfmiddlewaretoken]').value },
body: dataToBackEnd
})
fetch(request, {
method: 'POST',
mode: 'same-origin'
}).then(
function(response) {
if (response.status === 200) {
loadResults()
} else {
alert("Error")
}
}
)
}
</script>
В ваших представлениях вы добавите 2 представления, или только 1, если вы измените представление "ending" для получения поста и возврата http-ответа
views.py
def ajax_ending(req):
if req.method == "POST":
from_to_form = FromToForm(req.POST)
if from_to_form.is_valid():
start = datetime.combine(from_to_form.cleaned_data['start_date'], from_to_form.cleaned_data['start_time']).isoformat()
end = datetime.combine(from_to_form.cleaned_data['end_date'], from_to_form.cleaned_data['end_time']).isoformat()
# i don't understand why you are executing queries like this, so i assume they work
with connections["mssql_database"].cursor() as cursor:
cursor.execute("EXEC read_unended @dt_od='%s', @dt_do='%s'" % (start, end))
result = cursor.fetchall()
context['result'] = result
return HttpResponse(status=200)
else:
return HttpResponse(status=400)
else:
return HttpResponse(status=405)
def ajax_load_results(request):
if request.method == "GET":
if request.user:
# get the activities
context =
return render(request, 'ajax-ending.html', {"context": context})
else:
return HttpResponse(status=403)
else:
return HttpResponse(status=405)
И у вас будет еще один template.html только для tbody таблицы
ajax-ending.html
{% for i in result %}
<tr>
<td id="tdId_{{ i.id }}0">{{i.0}}</td>
<td id="tdId_{{ i.id }}1">{{i.1}}</td>
<td id="tdId_{{ i.id }}2">{{i.2}}</td>
<td id="tdId_{{ i.id }}3">{{i.3}}</td>
<td id="tdId_{{ i.id }}4">CELL TO INSERT END TIME*</td>
<td id="tdId_{{ i.id }}5">{{i.5}}</td>
<td id="tdId_{{ i.id }}6">{{i.6}}</td>
<td><button value="{{i.id}}" type="button" onclick="setEndActivity(this.value)">End</button><td/>
</tr>
{% endfor %}
(Не тестировалось, если возникнет ошибка, дайте мне знать)