Django rychlost cyklu for v templates

Django rychlost cyklu for v templates
« kdy: 15. 12. 2022, 13:37:32 »
Zdravím všechny vespolek,
mám problém s rychlostí vykreslování dat v templates. Mám aplikaci typu dodací list s proměnným počtem položek.
V databázi mám zvlášť tabulku pro dodací list a položku dodacího listu. Ve html view mám seznam dodáků i položkami a to mi dělá problémy s rychlostí, stránka s cca 100 dodacími listy se zobrazuje zhruba 7 sekund a to je moc. Mám to řešené tak že se vypíše  dodák a pak prohledává celé tabulka s položkami a hledá ty které patří k dodáku. Takže cyklus prohledání všech položek se zopakuje ke každému dodáku. Nemáte někdo nápad jak by to šlo zjednodušit či zrychlit?
Díky moc za jakýkoliv nápad.


Re:Django rychlost cyklu for v templates
« Odpověď #1 kdy: 15. 12. 2022, 13:55:05 »
Co zobrazujete v te tabulce? Proc prochazite polozky pro kazdy list?

Re:Django rychlost cyklu for v templates
« Odpověď #2 kdy: 15. 12. 2022, 14:05:49 »
je tam tabulka všech dodacích listů i s položkami kód viz níže,
ten druhý for mi dělá potíže je to asi 1000 položek


{% for item in model %}
<tr>
<td><a href="{% url 'dodak:DodakEdit' item.id %}"><i class="fa fa-pencil-square-o">[/url]
<a href="{% url 'dodak:DodakPrint' item.id  %} " target="_blank"><i class="fa fa-print">[/url]
<a href="pdf/{{item.id }}"><i class="fa fa-file-pdf-o" aria-hidden="true">[/url]
</td>
<td><a href="{% url 'dodak:DodakView' item.id %}">{{ item.cisloDodaku }}[/url]
</td>
<td>{{ item.datumVytvoreni }}</td>
<td>{{ item.projekt }}</td>
<td>{{ item.adresaOdberatel|slice:"20" }}</td>
<td>{{ item.cisloObjednavky }}</td>
<td>
 
{% for itemsx in items  %}
     {% if itemsx.dodak == item %}
               {{ itemsx.polozka|slice:"20"  }}

      {% endif %}
 {% endfor %}
 </td>
 <td>{% if item.soubor %}Ano{% else %}Ne{% endif %}</td>
 <td>{% if item.vyuctovano %}Ano{% else %}Ne{% endif %}</td>
</tr>
 {% endfor %}

Bugsa

  • ***
  • 118
    • Zobrazit profil
    • E-mail
Re:Django rychlost cyklu for v templates
« Odpověď #3 kdy: 15. 12. 2022, 14:10:55 »
Já bych to tedy udělal jinak. Do seznamu si načtu jen ty hlavičky dodacích listů a až po kliknutí bych si dočetl položky. Proč to načítáš vše najednou?

Bugsa

  • ***
  • 118
    • Zobrazit profil
    • E-mail
Re:Django rychlost cyklu for v templates
« Odpověď #4 kdy: 15. 12. 2022, 14:18:23 »
Nebo když už to chceš mít vše přednačtené a bez AJAXu, tak bych změnil model tak, aby už konkrétní dodák obsahoval ve svém atributu právě jen své položky a ty pak for cyklem vypíšeš bez nutnosti procházení celého listu všech položek všech dodáků.

{% for itemsx in item.polozky  %}
     {{ itemsx.polozka|slice:"20"  }}
{% endfor %}


Re:Django rychlost cyklu for v templates
« Odpověď #5 kdy: 15. 12. 2022, 14:33:25 »
Všechno najednou načítám kvůli jednoduššímu vyhledávání, které mi obsluhuje js v tabulce

Re:Django rychlost cyklu for v templates
« Odpověď #6 kdy: 15. 12. 2022, 14:41:01 »
Nebo když už to chceš mít vše přednačtené a bez AJAXu, tak bych změnil model tak, aby už konkrétní dodák obsahoval ve svém atributu právě jen své položky a ty pak for cyklem vypíšeš bez nutnosti procházení celého listu všech položek všech dodáků.

{% for itemsx in item.polozky  %}
     {{ itemsx.polozka|slice:"20"  }}
{% endfor %}

Úplně přesně nechápu jak to myslíš, když je proměnný počet položek. Můžeš mi prosím poslat nějaký příklad?

Bugsa

  • ***
  • 118
    • Zobrazit profil
    • E-mail
Re:Django rychlost cyklu for v templates
« Odpověď #7 kdy: 15. 12. 2022, 14:54:54 »
Na počtu položek vůbec nezáleží. Musíš udělat změnu na backendu (model a načítání dat do něj) ještě před vykreslením template.

Jak jsem psal výše, položky dodáku budou atributem dodáku (bude to list, nezajímá tě jeho délka = splňuje tvůj požadavek na dynamický počet položek). Při načítání dodacích listů z databáze si rovnou načteš i jeho položky. Třeba přes relaci viz můj vymyšlený příklad níže.

Abych ti mohl konkrétněji poradit, potřeboval bych vidět tvoje modely a metody načítání dat.

Kód: [Vybrat]
from django.db import models

class Dodak(models.Model):
    id = models.AutoField(primary_key=True)
    polozky = models.oneToMany()

class PolozkaDodaku(models.Model):
    dodak = models.ForeignKey(Dodak, on_delete=models.RESTRICT) 


_Jenda

  • *****
  • 1 573
    • Zobrazit profil
    • https://jenda.hrach.eu/
    • E-mail
Re:Django rychlost cyklu for v templates
« Odpověď #9 kdy: 15. 12. 2022, 15:40:40 »
Já tomu nerozumím, ale takhle na první pohled mi přijde jestli to není kvadratické? Tj. v hlavním for cyklu vypisuješ dodáky a pak ve vnořeném procházíš všechny znova abys pokaždé jen vybral tím ifem ten jeden co zrovna zpracováváš?
{% for item in model %} // pro všechny dodáky
// vypiš hlavičku dodáku

{% for itemsx in items  %} // co je items? neprocházíš všechny dodáky znova?
     {% if itemsx.dodak == item %}
               {{ itemsx.polozka|slice:"20"  }}

     {% endif %}
{% endfor %}
{% endfor %}

Re:Django rychlost cyklu for v templates
« Odpověď #10 kdy: 15. 12. 2022, 17:44:22 »
Přesně jak říkáš, já si první vypíšu obsah dodáku (číslo adresa datum atd) a pak hledám v dalším tabulce ve které jsou jen návzi položek a relace
takhle vypadá model

class DodakModel(models.Model):
    uuid = ShortUUIDField(unique=True)
    projekt = models.ForeignKey(ProjektModel, on_delete=models.CASCADE, related_name='projekt')
    vlastnik = models.ForeignKey(User,on_delete=models.CASCADE)
    datumVytvoreni = models.DateTimeField(default=timezone.now, editable=False)
    datumVystaveni = models.DateTimeField(default=timezone.now)
    cisloDodaku = models.CharField(max_length=20)
    adresaOdberatel = models.TextField(max_length=200)
    adresaDodavatel = models.TextField(max_length=200)
    atd.

    def __str__(self):
        return self.cisloDodaku

class DodakPolozkaModel(models.Model):
    dodak = models.ForeignKey(DodakModel,on_delete=models.CASCADE,related_name='dodak')
    polozka = models.CharField(max_length=75)
    pocet = models.IntegerField(default=1)
 

Bugsa

  • ***
  • 118
    • Zobrazit profil
    • E-mail
Re:Django rychlost cyklu for v templates
« Odpověď #11 kdy: 15. 12. 2022, 18:36:04 »
No vidíš, ty tam tu relaci Dodák -> Položka už máš.
Kód: [Vybrat]
   
class DodakPolozkaModel(models.Model):
   dodak = models.ForeignKey(DodakModel,on_delete=models.CASCADE,related_name='dodak')

Tak by mělo jít v template zavolat foreach cyklus na položkách dodáku
Kód: [Vybrat]
{% for itemsx in item.dodak_set.objects.all() %}
     {{ itemsx.polozka|slice:"20"  }}
{% endfor %}

Až to rozchodíš, tak bys měl zvážit nějaké stránkování. Až tam budeš mít tisíce dokladů, tak to zase bude pomalé. Proto doporučuji spíš způsob

Citace: Bugsa
Do seznamu si načtu jen ty hlavičky dodacích listů a až po kliknutí bych si dočetl položky.

Re:Django rychlost cyklu for v templates
« Odpověď #12 kdy: 15. 12. 2022, 18:58:59 »
Šak tak to mám už teď, jen v djangu jsem foreach nenašel tak jsem použil for.
stránkování jsem tam měl, ale chtěl jsem použít něco takového
https://www.jqueryscript.net/demo/Paginate-Sort-Filter-Table-Sortable/

Re:Django rychlost cyklu for v templates
« Odpověď #13 kdy: 15. 12. 2022, 20:52:12 »
Přemýšlel jsem jestli by to nešlo plnit ve funkci co volám ve view, kde by se to plnilo do jedné proměnné abych se vyhl druhému cyklu

Bugsa

  • ***
  • 118
    • Zobrazit profil
    • E-mail
Re:Django rychlost cyklu for v templates
« Odpověď #14 kdy: 16. 12. 2022, 07:09:11 »
Šak tak to mám už teď, jen v djangu jsem foreach nenašel tak jsem použil for.

Sorry, jsem zvyklý na terminologii C#. V Pythonu se mezi foreach (for pro iterátor) a for (range od-do) nerozlišuje.

Nemáš to tak už teď. Tvůj způsob z prvního příspěvku prochází pro každý item dodáku celý list položek a podmínkou hledá jestli se položka rovná dodáku. Můj navrhovaný způsob tento nesmysl nedělá. V přípravě modelu se už načtou správné položky a template pak už rovnou ve for cyklu vypíše pouze položky konkrétního dodáku, tedy se to zákonitě musí hodně zrychlit.

Přemýšlel jsem jestli by to nešlo plnit ve funkci co volám ve view, kde by se to plnilo do jedné proměnné abych se vyhl druhému cyklu

Ano. Řešení je spousta. Hlavně se vyhni složitým operacím s daty v template, to je největši brzda.
« Poslední změna: 16. 12. 2022, 07:15:53 od Bugsa »