В своем тренировочном проекте столкнулся с следующей проблемой. В проекте есть старницы где формы подгружаются динамически в виде таблице с произвольным количеством полей.
Все работает информация в БД записывается формы подгружаются, но есть две проблемы.
ConnectionAbortedError: [WinError 10053] Программа на вашем хост-компьютере разорвала установленное подключение
Код Forms.py
class OperationAssembly(forms.Form):
def __init__(self, *args, **kwargs):
quantity_of_fileds = kwargs.pop('quantity_of_fileds')
self.current_user_id = kwargs.pop('current_user_id')
super(OperationAssembly, self).__init__(*args, **kwargs)
self.fields["start_date"] = forms.DateTimeField(initial=now, label='Дата сборки')
self.fields['type_of_defect'] = forms.CharField(initial="Годная", label='Причина отбраковки', required=False)
self.fields['serial_number'] = forms.CharField(label="Серийный номер")
self.fields['type_of_product'] = ModelChoiceField_Label2(queryset=Type_of_product.objects.all(),
empty_label=None, label="Тип изделия")
for i in range(1, quantity_of_fileds + 1):
self.fields["Component {}".format(i)] = forms.CharField(label="С/Н Компонента №{}".format(i))
def clean_type_of_defect(self):
data = self.cleaned_data['type_of_defect']
if data == '':
return 3
else:
return Type_of_defect.objects.get_or_create(label=data)[0].id
def clean(self):
super(OperationAssembly, self).clean()
# Сравниваю каждое поле с каждым на повторы
for field1, field2 in itertools.combinations(self.fields, 2):
if self.cleaned_data[field1] == self.cleaned_data[field2]:
raise forms.ValidationError("Поля формы не должны повторяться")
def list_of_assembly(self):
list_components = []
for k in self.fields:
if k.startswith("Component"):
list_components.append(self.cleaned_data[k])
# Получаем словарь с списком последних id из внесенных деталей
temp_query = Product.objects.filter(serial_number__in=list_components).values('serial_number').annotate(max_id=Max('id'))
return temp_query
def save(self):
add_product = Product.objects.create(serial_number=self.cleaned_data['serial_number'],
type_of_product_id_id=self.cleaned_data['type_of_product'].id)
add_product.save()
new_product_id = add_product.id
list_of_assembly = self.list_of_assembly()
for i in list_of_assembly:
connection.cursor().execute('insert into "mainapp_product_Assembly" (from_product_id, to_product_id)'
' values ({},{});'.format(new_product_id, i["max_id"]))
add_operation = Operation_history.objects.create(start_date=self.cleaned_data['start_date'],
end_date=self.cleaned_data['start_date'],
employess_id_id=self.current_user_id.id,
type_of_defect_id_id=self.cleaned_data['type_of_defect'],
type_of_operation_id_id=6)
add_operation.save()
list_of_char = Characteristic_of_product.objects.filter(type_of_product_id_id=self.cleaned_data['type_of_product'].id)
for char in list_of_char:
add_char = Product_2_characteristic.objects.create(value="NULL",
characteristic_of_product_id_id=char.id,
operation_history_id_id=add_operation.id,
product_id_id=add_product.id)
add_char.save()
Код views.py
def operation_assembly_form(request, quantity_of_fields):
current_form = str(base64.b64encode(bytearray(str(uuid.uuid4()).encode("utf-8"))))[2:-1]
if request.method == "GET":
form = OperationAssembly(quantity_of_fileds=quantity_of_fields,
current_user_id=Employess.objects.get(user_id=request.user.id))
elif request.method == "POST":
form = OperationAssembly(request.POST, quantity_of_fileds=quantity_of_fields,
current_user_id=Employess.objects.get(user_id=request.user.id))
if form.is_valid():
form.save()
else:
return HttpResponse(form.errors.as_json(), content_type='application/json')
return render(request, 'operation_assembly_form.html', {'form': form, 'current_form': current_form,
'quantity_of_fields': quantity_of_fields})
Код подгружаемого html блока
<div id="{{ current_form }}">
<form class="allforms" id="operation_formset" method="POST" action="/mainapp/add/operation/assembly/form/{{ quantity_of_fields }}/">
{% csrf_token %}
<table>
<tr>
{% for field in form %}
<td>
{{ form.errors }}
{{ field.label_tag }}
</td>
{% endfor %}
</tr>
<tr>
{% for field in form %}
<td>
{{ form.errors }}
{{ field }}
</td>
{% endfor %}
<td>
<button type="button" id="{{ current_form }}_plus" class="btn btn-light">+</button>
</td>
<script>
$('#{{ current_form }}_plus').on('click', function() {
$.get('/mainapp/add/operation/assembly/form/' + ({{ quantity_of_fields }} + 1) + '/', function(data) {
$('#{{ current_form }}').html(data);
});
});
</script>
</tr>
</table>
</form>
</div>
Код основной html старницы
{% extends "operation_menu.html" %}
{% block chosen_operation %}
<h1>Провести операции:</h1>
<div id="add_form"></div>
<button id="plus" class="btn btn-light">+</button>
<button id="save" class="btn btn-light">Внести информацию о изделиях</button>
<script>
$('#plus').click(function() {
$.ajax({
url: 'form/1',
success: function(data){
$('#add_form').append(data);
}
});
});
$("#save").click(function(){
$('.allforms').each(function(){
valuesToSend = $(this).serialize();
form_id = $(this).find('button');
$.ajax($(this).attr('action'),
{
method: $(this).attr('method'),
data: valuesToSend,
success: function (data) {
console.log(data)
console.log(form_id.attr('id').slice(0, 48))
console.log($(this).attr('action'))
if (data.__all__) {
$.get($(this).attr('action'), function(data) {
$('#form_id').html(data);
});
}
}
}
)
});
});
</script>
{% endblock %}
views.py
if form.is_valid():
form.save()
else:
response = {}
for k in form.errors:
response[k] = form.errors[k][0]
return JsonResponse({"response": response, 'result': 'error'})
В js-файл в ajax
запрос в success
добавьте условие
if (data.result == 'error') {
//Логика для вывода ошибок
}
На данный момент нужного эффекта в поведении формы я добился следующим кодом.
views.py
def operation_assembly_form(request, quantity_of_fields):
current_form = str(base64.b64encode(bytearray(str(uuid.uuid4()).encode("utf-8"))))[2:-1]
if request.method == "GET":
form = OperationAssembly(quantity_of_fileds=quantity_of_fields,
current_user_id=Employess.objects.get(user_id=request.user.id))
elif request.method == "POST":
form = OperationAssembly(request.POST, quantity_of_fileds=quantity_of_fields,
current_user_id=Employess.objects.get(user_id=request.user.id))
if form.is_valid():
form.save()
return render(request, 'operation_assembly_form.html', {'form': form, 'current_form': current_form,
'quantity_of_fields': quantity_of_fields})
Код общего шаблона страницы.
{% extends "operation_menu.html" %}
{% block chosen_operation %}
<h1>Провести операции:</h1>
<div id="add_form"></div>
<button id="plus" class="btn btn-light">+</button>
<button id="save" class="btn btn-light">Внести информацию о изделиях</button>
<script>
$('#plus').click(function() {
$.ajax({
url: 'form/1',
success: function(data){
$('#add_form').append(data);
}
});
});
$("#save").click(function(){
Can_i_redirect = 0
$('.allforms').each(function(){
valuesToSend = $(this).serialize();
form_id = $(this).find('button');
$.ajax($(this).attr('action'),
{
method: $(this).attr('method'),
data: valuesToSend,
context:this,
async:false,
success: function (data) {
console.log(data.slice(63, -6))
$(this).html(data.slice(63, -6));
console.log(data.indexOf('errorlist'))
if (data.indexOf('errorlist') != -1) {
Can_i_redirect += 1
console.log(Can_i_redirect)
}
}
});
console.log(Can_i_redirect)
if (Can_i_redirect == 0) {
$(location).attr('href','/mainapp/add/operation/assembly/')
}
});
});
</script>
{% endblock %}
Код вставляемых шаблонов.
<div id="{{ current_form }}">
<form class="allforms" id="operation_formset" method="POST" action="/mainapp/add/operation/assembly/form/{{ quantity_of_fields }}/">
{% csrf_token %}
<table>
<tr>
{% for field in form %}
<td>
{{ field.errors }}
{{ field.label_tag }}
</td>
{% endfor %}
</tr>
<tr>
{% for field in form %}
<td>
{{ field }}
</td>
{% endfor %}
<td>
<button type="button" id="{{ current_form }}_plus" class="btn btn-light">+</button>
</td>
<script>
$('#{{ current_form }}_plus').on('click', function() {
$.get('/mainapp/add/operation/assembly/form/' + ({{ quantity_of_fields }} + 1) + '/', function(data) {
$('#{{ current_form }}').html(data);
});
});
</script>
</tr>
</table>
</form>
</div>
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab