'When saving ModelFormSet it reads the whole underlying table?
I don't know how to explain the problem in my title, so if someone knows how to better phrase the problem I'm going to describe, I hope there is a way to update the tile.
I have to say I already tried to search with google, for a solution, but I'm not able to find something useful I tried to follow there video tutorial (after reading the official Django documentation of course) Video 01 Video 02
I'm using an old version of Django, because I have to connect to MS SQL Database, and this mix of python+django+mssql-backend is the only combination found functioning (I tried with the latest version of Django and Python, but I had to mess around with the mssql-backend because there were a lot of error about deprecated function, for example ugettext_lazy instead of gettext_lazy and many more...)
I'm trying to create a small interface to an already existing MS SQL Database (so I can't change the structure of the database). I'm still learning Django, so I'm pretty sure the problem is mine, I have misunderstood something :(
Currenty I created a page to search the interesting rows in database table and a page to edit all the resulting rows from the previous search When I submit the form with the search parameter, I'm able to create a queryset to show the correct form to edit (for example search by customer number, customer name and so on). But when I edit something (for example I change the name of the customer...) and submit with the save button, the correct AnagraficheEditView (reported below) is "called" but I don't have the search filter anymore, so I can build the same queryset, the only thing I can do is
aefs = formset(request.POST or None, request.FILES or None)
The problem is: calling formset.is_valid() django tries to select from the underlying table all the rows (and I currently have about 16 millions rows in that table, so it's a little slow :) )
I think I'm missing something important here
Thanks for any suggestion
forms.py
from django import forms
from django.db.models import query
from django.utils.translation import gettext_lazy as _
from .models import Anagrafiche
class AnagraficheSearchForm(forms.Form):
idbatch = forms.IntegerField(required=True, label='ID Batch')
iderrore = forms.CharField(max_length=256, required=False, label='Errore')
codiceclifor = forms.CharField(max_length=64, required=False, label='Codice Cliente')
denominazione = forms.CharField(max_length=512, required=False, label='Denominazione')
cfisc = forms.CharField(max_length=16, required=False, label='Codice Fiscale')
piva = forms.CharField(max_length=11, required=False, label='Partita Iva')
class AnagraficheEditForm(forms.ModelForm):
class Meta:
model: Anagrafiche
fields = ['idbatch', 'mandante', 'societa', 'codiceclifor', 'nome', 'cognome', 'ragsoc', 'cfisc', 'piva', 'codicedestinatariosdi', 'iderrore']
labels = {
'idbatch': _('ID Batch'),
'mandante': _('Mandante'),
'societa': _('Societa'),
'codiceclifor': _('Codice Cliente'),
'nome': _('Nome'),
'cognome': _('Cognome'),
'ragsoc': _('Ragione Sociale'),
'cfisc': _('Codice Fiscale'),
'piva': _('Partita Iva'),
'codicedestinatariosdi': _('Codice SDI'),
'iderrore': _('Errore'),
}
widgets = {
'idbatch': forms.HiddenInput(),
'mandante': forms.HiddenInput(),
'societa': forms.HiddenInput(),
'codiceclifor': forms.HiddenInput(),
}
Models.py
from django.db import models
from django.utils import translation
# Create your models here.
class Anagrafiche(models.Model):
idbatch = models.IntegerField(db_column='IDBatch', primary_key=True) # Field name made lowercase.
mandante = models.CharField(db_column='Mandante', max_length=64) # Field name made lowercase.
societa = models.CharField(db_column='Societa', max_length=64) # Field name made lowercase.
codiceclifor = models.CharField(db_column='CodiceCliFor', max_length=64) # Field name made lowercase.
nome = models.CharField(db_column='Nome', max_length=256, blank=True, null=True) # Field name made lowercase.
cognome = models.CharField(db_column='Cognome', max_length=256, blank=True, null=True) # Field name made lowercase.
ragsoc = models.CharField(db_column='RagSoc', max_length=256, blank=True, null=True) # Field name made lowercase.
#more fields here, removed for simplicity
cfisc = models.CharField(db_column='CFisc', max_length=32, blank=True, null=True) # Field name made lowercase.
piva = models.CharField(db_column='PIVA', max_length=32, blank=True, null=True) # Field name made lowercase.
codicedestinatariosdi = models.CharField(db_column='CodiceDestinatarioSDI', max_length=64, blank=True, null=True) # Field name made lowercase.
iderrore = models.IntegerField(db_column='IDErrore', blank=True, null=True) # Field name made lowercase.
class Meta:
managed = False
#SQL Schemas :)
db_table = 'enerp].[Anagrafiche'
unique_together = (('idbatch', 'mandante', 'societa', 'codiceclifor'),)
verbose_name = "Anagrafica"
verbose_name_plural = "Anagrafiche"
def __str__(self):
if self.cognome != None:
return self.codiceclifor + ' ' + self.cognome + ' ' + self.nome
else:
if self.ragsoc != None:
return self.codiceclifor + ' ' + self.ragsoc
else:
return self.codiceclifor
views.py
from django.db.models import Q
from django.db.models.query import QuerySet
from django.forms.models import modelformset_factory
from django.shortcuts import render
from .models import Anagrafiche
from .forms import AnagraficheSearchForm, AnagraficheEditForm
def ENERP(request):
return render(request, 'index.html')
def AnagraficheSearchView(request):
if request.method == 'GET':
asf = AnagraficheSearchForm(data=request.GET)
if asf.is_valid():
if asf.cleaned_data['idbatch'] != None:
qs = Anagrafiche.objects.filter(idbatch__exact=asf.cleaned_data['idbatch'])
if asf.cleaned_data['denominazione'] != '':
qs = qs.filter(Q(cognome__contains=asf.cleaned_data['denominazione']) | Q(nome__contains=asf.cleaned_data['denominazione']) | Q(ragsoc__contains=asf.cleaned_data['denominazione']))
if asf.cleaned_data['cfisc'] != '':
qs = qs.filter(cfisc__exact=asf.cleaned_data['cfisc'])
if asf.cleaned_data['piva'] != '':
qs = qs.filter(piva__exact=asf.cleaned_data['piva'])
return render(request, 'AnagraficheSearchPage.html', {'AnagraficheSearchForm' : asf})
else:
return render(request, 'AnagraficheSearchPage.html', {'AnagraficheSearchForm' : asf})
else:
return render(request, 'AnagraficheSearchPage.html')
def AnagraficheEditView(request):
formset = modelformset_factory(Anagrafiche, form=AnagraficheEditForm, extra=0)
if request.method == 'GET':
if request.GET.get('queryset') is None:
qs = Anagrafiche.objects.all()
if request.GET.get('idbatch') is not None:
qs = qs.filter(Q(idbatch__exact=request.GET.get('idbatch')))
if request.GET.get('denominazione') is not None:
qs = qs.filter(Q(cognome__contains=request.GET.get('denominazione')) |
Q(nome__contains=request.GET.get('denominazione')) |
Q(ragsoc__contains=request.GET.get('denominazione')))
if request.GET.get('cfisc') != '':
qs = qs.filter(cfisc__exact=request.GET.get('cfisc'))
if request.GET.get('piva') != '':
qs = qs.filter(piva__exact=request.GET.get('piva'))
aefs = formset(request.POST or None, request.FILES or None, queryset=qs)
context = {'AnagraficheEditFormSet' : aefs}
return render(request, 'AnagraficheEditPage.html', context)
elif request.method == 'POST':
aefs = formset(request.POST or None, request.FILES or None)
if 'AnagraficheEditSaveButton' in request.POST:
if aefs.is_valid(): # this become a select * from table with 16 million record
aefs.save()
context = {'AnagraficheEditFormSet' : aefs}
return render(request, 'AnagraficheEditPage.html', context)
else:
asf = AnagraficheSearchForm()
context = {'AnagraficheSearchForm' : asf}
return render(request, 'AnagraficheSearchPage.html', context)
urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.ENERP),
path('AnagraficheSearch', views.AnagraficheSearchView),
path('AnagraficheEdit', views.AnagraficheEditView),
]
Template AnagraficheEditPage.html
{% extends "layout.html" %}
{% block maincontent %}
<div class="container">
<div class="container-lg">
{% load crispy_forms_tags %}
<form id="AnagraficheEditForm" action="AnagraficheEdit" method="POST">
{% csrf_token %}
{{ AnagraficheEditFormSet.management_form|crispy }}
<div class="d-grid gap-5">
{% for aef in AnagraficheEditFormSet %}
{{ aef.idbatch }}
{{ aef.mandante }}
{{ aef.societa }}
{{ aef.codiceclifor }}
<div class="card">
<div class="card-body">
<h6 class="card-subtitle mb-2 text-muted">
<a href="#{{ aef.codiceclifor.value }}')">{{ aef.codiceclifor.value }}</a> -
{% if aef.cognome.value != None and aef.nome.value != None %}
{{ aef.cognome.value }} {{ aef.nome.value }}
{% elif aef.ragsoc.value != '' %}
{{ aef.ragsoc.value }}
{% endif %}
</h6>
<div class="row">
<div class="col-6">
{{ aef.cognome|as_crispy_field }}
</div>
<div class="col-6">
{{ aef.nome|as_crispy_field }}
</div>
</div>
<div class="row ma-1">
<div class="col-12">
{{ aef.ragsoc|as_crispy_field }}
</div>
</div>
<div class="row mt-1">
<div class="col-4">
{{ aef.cfisc|as_crispy_field }}
</div>
<div class="col-4">
{{ aef.piva|as_crispy_field }}
</div>
<div class="col-4">
{{ aef.codicedestinatariosdi|as_crispy_field }}
</div>
</div>
<div class="row mt-1">
<div class="col-4">
{{ aef.iderrore|as_crispy_field }}
</div>
<div class="col-8">
{{ aef.iderrore|as_crispy_field }}
</div>
</div>
</div>
</div>
{% if forloop.last == True %}
<div class="row justify-content-md-center mb-5">
<div class="col-md-auto">
<button id="AnagraficheEditSaveButton" name="AnagraficheEditSaveButton" type="submit" class="btn btn-primary">Salva</button>
</div>
</div>
{% endif %}
{% empty %}
<div class="card">
<div class="card-body">
<h6 class="card-subtitle mb-2 text-muted">Nessun anagrafica corrispondente ai criteri di ricerca</h6>
</div>
</div>
{% endfor %}
</div>
</form>
</div>
</div>
{% endblock %}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
