'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 %}

environment configuration



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source