Ajax-запрос в django
Я только начинаю изучать django: я пытаюсь использовать ajax-запросы и перезагрузить только tbody после того, как пользователь добавит или удалит строку таблицы. В html шаблоне у меня имеется таблица, а внутри тега script - функция загрузки таблицы, удаления и добавления строки. Мой код не работает: не удается сохранить запись в БД. Я полагаю, что ошибка заключается во views.py. Что я делаю не так?
HTML
<!--В цикле перечисленные все скрытые поля-->
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
<!--В цикле перечисленные все видимые поля указанные в AkpGroupForm в forms.py-->
<table class="table align-middle">
<thead>
<tr>
<th scope="col"></th>
<th scope="col">#</th>
{% if form.Group.visible_fields %}
{% for field in form.Group.visible_fields %}
<th scope="col">{{ field.label }}</th>
{% endfor %}
{% endif %}
<th>Действие</th>
</tr>
</thead>
<tbody id="table_person_id">
{% if persons %}
{% for person in persons %}
<tr>
<th scope="row"><div><input class="form-check-input" type="checkbox" id="checkboxNoLabel1" value="" aria-label="..."></div></th>
<th scope="row">1</th>
{% if form.Group.visible_fields %}
{% for field in form.Group.visible_fields %}
<td>{{ field }}</td>
{% endfor %}
{% endif %}
<td>
<button value="{{AkpGroup.Id_Group}}" onclick=delete_person>Удалить</button>
</td>
</tr>
{% endfor %}
{% endif %}
</tbody>
<tfoot>
<form method="POST" onsubmit=add_person>
<tr>
<th scope="row"></th>
<th scope="row"></th>
{% if form.Group.visible_fields %}
{% for field in form.Group.visible_fields %}
<td>{{ field }}</td>
{% endfor %}
{% endif %}
<td>
<button type="submit">Добавить</button>
</td>
</tr>
</form>
</tfoot>
</table>
<script>
function loadTable() {
let xhttpTableGrops = new XMLHttpRequest()
xhttpTableGrops.onreadystatechange = function (data) {
if (this.readyState === 4 && this.status === 200) {
document.getElementById("table_person_id").innerHTML = this.response
}
}
xhttpTableGrops.open("GET", "./url_to_django/load_table/", true)
xhttpTableGrops.send()
}
function delete_person(Id_Group) {
const request = new Request(`./url_to_django/delete-person/${Id_Group}`,
{
method: "DELETE",
<!-- headers: { 'X-CSRFToken': document.querySelector('[name=csrfmiddlewaretoken]').value }-->
}
)
fetch(request, {
method: "DELETE",
mode: 'same-origin'
}).then(
function (response) {
if (response.status === 200) {
loadTable()
} else {
alert("error")
}
}
)
}
function add_person(e) {
e.preventDefault()
const dataToBackEnd = new FormData()
dataToBackEnd.append("Id_Incidents", document.getElementById("Id_Incidents").value)
dataToBackEnd.append("Type_Participation", document.getElementById("Type_Participation").value)
dataToBackEnd.append("Id_People", document.getElementById("Id_People").value)
dataToBackEnd.append("Competencies", document.getElementById("Competencies").value)
const request = new Request('.url_to_django/add-person/',
{
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 === 201) {
loadTable()
} else {
alert("error")
}
}
)
}
</script>
Views.py
class Groups(CreateView):
error = ''
form_class = GroupCheckResultMeetingCreationMultiForm
success_url = reverse_lazy('group')
template_name = 'main/group.html'
def form_valid(self, form):
if form.is_valid() and 'next':
form['Group'].save()
# form['CheckResult'].save()
# form['Meeting'].save()
# group_created = form['Group'].save(commit=False)
# group_created.Id_Incidents = get_object_or_404(AkpIncidents, Id_Incidents=id_incidents)
# group_created.save()
#
# check_result_created = form['CheckResult'].save(commit=False)
# check_result_created.Id_Incidents = get_object_or_404(AkpIncidents, Id_Incidents=id_incidents)
# check_result_created.save()
#
# meeting_created = form['Meeting'].save(commit=False)
# meeting_created.Id_Incidents = get_object_or_404(AkpIncidents, Id_Incidents=id_incidents)
# meeting_created.save()
else:
error = 'Форма заполнена некорректно'
# elif 'back' in request.POST:
# return redirect('main:incident')
data = {
'form': 'form',
# 'GroupForm': 'Group',
'error': 'error'
}
return redirect(self.get_success_url(), data)
# return render(form, 'main/group.html', data)
# def is_valid(self):
# return all(form.is_valid() for form in self.forms.values())
def load_table(request, persons):
error = ''
if request.method == "GET":
if request.user:
if id_incidents:
persons = AkpGroup.objects.get(Id_Incidents=id_incidents) # запрос в базу данных
else:
error = 'id_incidents не обнаружен'
return render(request, 'main/group.html', {"person": persons}, {"error": error})
else:
return HttpResponse(status=403)
else:
return HttpResponse(status=405)
def delete_person(request, Id_Group):
if request.method == "DELETE":
if request.user:
person_to_delete = AkpGroup.objects.get(id=Id_Group)
person_to_delete.delete()
return HttpResponse(status=200)
else:
return HttpResponse(status=403)
else:
return HttpResponse(status=405)
def add_person(request):
if request.method == "POST":
if request.user:
form = AkpGroupForm(request.POST) # форма, созданная в forms.py чтобы добавить участника
if form.is_valid():
# group_created = form['Group'].save(commit=False)
# group_created.Id_Incidents = get_object_or_404(AkpIncidents, Id_Incidents=id_incidents)
# group_created.save()
Id_Incidents = form.cleaned_data['Id_Incidents']
Id_People = form.cleaned_data['Id_People']
Competencies = form.cleaned_data['Competencies']
Type_Participation = form.cleaned_data['Type_Participation']
new_person = AkpGroup(
Id_Incidents=Id_Incidents,
Id_People=Id_People,
Competencies=Competencies,
Type_Participation=Type_Participation,
)
new_person.save()
return HttpResponse(status=201)
else:
return HttpResponse(status=400)
else:
return HttpResponse(status=403)
else:
return HttpResponse(status=405)
Urls.py
app_name = "main"
urlpatterns = [
path('', views.start, name="start"),
path('incident', views.incident, name="incident"),
path('victim', views.victim, name="victim"),
path('group', views.Groups.as_view(), name='group'),
path('AdditionalDetail', views.additional_detail, name='AdditionalDetail'),
path('events', views.events, name='events'),
path('monitoring', views.monitoring, name='monitoring'),
path(
'url_to_django/delete-person/<int:Id_Group>',
views.delete_person,
name='delete_person'),
path(
'url_to_django/add-person/',
views.add_person,
name='add_person'),
path(
'url_to_django/load_table/',
views.load_table,
name='load_table')
]
Forms.py
class AkpGroupForm(ModelForm):
required_css_class = 'required'
class Meta:
model = AkpGroup
fields = ['Id_Incidents', 'Type_Participation', 'Id_People', 'Competencies']
# exclude = ('Id_Incidents',)
widgets = {
"Id_Incidents": Select(attrs={
'class': 'form-select'
}),
"Type_Participation": Select(attrs={
'class': 'form-select',
'style': 'height: 40px'
}),
"Id_People": Select(attrs={
'class': 'form-select',
'style': 'height: 40px'
}),
"Competencies": Textarea(attrs={
'class': 'form-select',
'style': 'height: 40px'
})
}
class AkpCheckResultForm(ModelForm):
required_css_class = 'required'
class Meta:
model = AkpCheckResult
fields = ['Id_Incidents', 'Inspector', 'Company', 'Post', 'Basis_Attraction', 'Check_Area']
exclude = ('Id_Incidents',)
widgets = {
"Id_Incidents": Select(attrs={
'class': 'form-select'
}),
"Inspector": Select(attrs={
'class': 'form-select',
'style': 'height: 60px'
}),
"Company": Textarea(attrs={
'class': 'form-select',
'style': 'height: 60px'
}),
"Post": Textarea(attrs={
'class': 'form-select',
'style': 'height: 60px'
}),
"Basis_Attraction": Textarea(attrs={
'class': 'form-select',
'style': 'height: 60px'
}),
"Check_Area": Textarea(attrs={
'class': 'form-select',
'style': 'height: 60px'
})
}
class AkpMeetingForm(ModelForm):
required_css_class = 'required'
class Meta:
model = AkpMeeting
fields = ['Id_Incidents', 'Date_Time', 'Location', 'Responsible']
exclude = ('Id_Incidents',)
widgets = {
"Id_Incidents": Select(attrs={
'class': 'form-select'
}),
"Date_Time": DateTimeInput(attrs={
'class': 'form-control',
'type': 'Date'
}),
"Location": TextInput(attrs={
'class': 'form-select',
'style': 'height: 40px'
}),
"Responsible": TextInput(attrs={
'class': 'form-select'
})
}