1
\$\begingroup\$

The problem is in the for loop because it do many repetitions and they are slow. For generate a table 40x40 it need about 20 seconds (I will need a table 200x200).

I think this is the relevant code. I draw the table in html using javascript but that part is fast

My view:

@staff_member_required
def trova_conoscenze_rapporti(request):
    if request.is_ajax():
        tipo_primo = request.POST.get('tipo_primo', None)
        primo_elemento = request.POST.get('primo_elemento', None)
        secondo_elemento_tipo = request.POST.get('tipo_secondo', None)
        context_dict={}
        primi=[]
        secondi=[]
        lista_primo=[]
        lista_secondo=[]
        lista_conoscenze=[]
        lista_rapporti=[]
        valori_conoscenza=[]
        valori_rapporto=[]
        posseduto=[]

        conoscenze=campaign.Conoscenza.objects.all()
        for valore in conoscenze:
            valori_conoscenza.append(valore.name)
        rapporti=campaign.Confidence.objects.all()
        for valore in rapporti:
            valori_rapporto.append(valore.name)

        if tipo_primo == 's':
            if primo_elemento == '':
                primi = affiliation.Schieramento.objects.all()
            else:
                primi.append(affiliation.Schieramento.objects.get(id=primo_elemento))
            if secondo_elemento_tipo == 's':
                secondi = affiliation.Schieramento.objects.all()
                for elemento_primo in primi:
                    lista_primo.append(elemento_primo.name)
                    for elemento_secondo in secondi:
                        sch_sch=services.get_sch_sch(elemento_primo, elemento_secondo)
                        lista_conoscenze.append(sch_sch.conoscenza.name)
                        lista_rapporti.append(sch_sch.rapporto.name)
            elif secondo_elemento_tipo == 'a':
                secondi = affiliation.Affiliation.objects.all()
                for elemento_primo in primi:
                    lista_primo.append(elemento_primo.name)
                    for elemento_secondo in secondi:
                        sch_aff=services.get_sch_sch(elemento_primo, 
                            elemento_secondo.schieramento)
                        lista_conoscenze.append(sch_aff.conoscenza.name)
                        lista_rapporti.append(sch_aff.rapporto.name)
            elif secondo_elemento_tipo == 'r':
                secondi = regent.Regent.objects.all()
                for elemento_primo in primi:
                    lista_primo.append(elemento_primo.name)
                    for elemento_secondo in secondi:
                        sch_reg=services.get_sch_sch(elemento_primo, 
                            elemento_secondo.first_affiliation().affiliazione.schieramento)
                        lista_conoscenze.append(sch_reg.conoscenza.name)
                        lista_rapporti.append(sch_reg.rapporto.name)

        elif tipo_primo == 'a':
            if primo_elemento == '':
                primi = affiliation.Affiliation.objects.all()
            else:
                primi.append(affiliation.Affiliation.objects.get(id=primo_elemento))
            if secondo_elemento_tipo == 's':
                secondi = affiliation.Schieramento.objects.all()
                for elemento_primo in primi:
                    lista_primo.append(elemento_primo.name)
                    for elemento_secondo in secondi:
                        aff_sch=services.get_sch_sch(
                            elemento_primo.schieramento, elemento_secondo)
                        lista_conoscenze.append(aff_sch.conoscenza.name)
                        lista_rapporti.append(aff_sch.rapporto.name)
            elif secondo_elemento_tipo == 'a':
                secondi = affiliation.Affiliation.objects.all()
                for elemento_primo in primi:
                    lista_primo.append(elemento_primo.name)
                    for elemento_secondo in secondi:
                        aff_aff=services.get_a_a(elemento_primo, elemento_secondo)
                        lista_conoscenze.append(aff_aff.conoscenza.name)
                        lista_rapporti.append(aff_aff.rapporto.name)
            elif secondo_elemento_tipo == 'r':
                secondi = regent.Regent.objects.all()
                for elemento_primo in primi:
                    lista_primo.append(elemento_primo.name)
                    for elemento_secondo in secondi:
                        aff_reg=services.get_r_a(elemento_secondo, elemento_primo)
                        lista_conoscenze.append(aff_reg.conoscenza.name)
                        lista_rapporti.append(aff_reg.rapporto.name)

        elif tipo_primo == 'r':
            if primo_elemento == '':
                primi = regent.Regent.objects.all()
            else:
                primi.append(regent.Regent.objects.get(slug=primo_elemento))
            if secondo_elemento_tipo == 's':
                secondi = affiliation.Schieramento.objects.all()
                for elemento_primo in primi:
                    lista_primo.append(elemento_primo.name)
                    for elemento_secondo in secondi:
                        reg_sch=services.get_sch_sch(
                            elemento_primo.first_affiliation().affiliazione.schieramento, 
                            elemento_secondo)
                        lista_conoscenze.append(reg_sch.conoscenza.name)
                        lista_rapporti.append(reg_sch.rapporto.name)
            elif secondo_elemento_tipo == 'a':
                secondi = affiliation.Affiliation.objects.all()
                for elemento_primo in primi:
                    lista_primo.append(elemento_primo.name)
                    for elemento_secondo in secondi:
                        reg_aff=services.get_r_a(elemento_primo, elemento_secondo)
                        lista_conoscenze.append(reg_aff.conoscenza.name)
                        lista_rapporti.append(reg_aff.rapporto.name)
            elif secondo_elemento_tipo == 'r':
                secondi = regent.Regent.objects.all()
                for elemento_primo in primi:
                    lista_primo.append(elemento_primo.name)
                    for elemento_secondo in secondi:
                        reg_reg=services.get_r_r(elemento_primo, elemento_secondo)
                        lista_conoscenze.append(reg_reg.conoscenza.name)
                        lista_rapporti.append(reg_reg.rapporto.name)
            elif secondo_elemento_tipo == 'e':
                secondi = exe.Exe.objects.all()
                for elemento_primo in primi:
                    lista_primo.append(elemento_primo.name)
                    for elemento_secondo in secondi:
                        reg_exe=services.get_reg_exe(elemento_primo, elemento_secondo)
                        lista_conoscenze.append(reg_exe.conoscenza.name)
                        posseduto.append(reg_exe.posseduto)

        for elemento_secondo in secondi:
            if secondo_elemento_tipo == 'e':
                exe_name=(elemento_secondo.colonna, elemento_secondo.riga)
                lista_secondo.append(exe_name)
            else:
                lista_secondo.append(elemento_secondo.name)

        response = json.dumps({'lista_primo': lista_primo, 
            'lista_secondo': lista_secondo, 
            'lista_conoscenze': lista_conoscenze, 
            'lista_rapporti': lista_rapporti,
            'valori_conoscenza': valori_conoscenza, 
            'valori_rapporto': valori_rapporto,
            'posseduto': posseduto
        })
        return HttpResponse(response, content_type='application/json') 

My services.get_r_r:

def get_r_r(reggente1, reggente2):
    if reggente1==reggente2:
        c=campaign.Conoscenza(name='Approfondita')
        r=campaign.Confidence(name='Fanatico')
        rr=regent.Regent_Relation(regent1=reggente1, regent2=reggente2, 
                conoscenza=c, rapporto=r)
    try:
        rr=regent.Regent_Relation.objects.get(regent1=reggente1, 
            regent2=reggente2)
        return rr
    except:
        try:
            rr=regent.Regent_Relation.objects.get(regent1=reggente2, 
                regent2=reggente1)
            rr=regent.Regent_Relation(regent1=reggente1, regent2=reggente2, 
                conoscenza=rr.conoscenza, rapporto=rr.rapporto)
            return rr
        except:
            fa=reggente2.first_affiliation().affiliazione
            rfa=get_r_a(reggente1, fa)
            rr=regent.Regent_Relation(regent1=reggente1, regent2=reggente2, 
                conoscenza=rfa.conoscenza, rapporto=rfa.rapporto)
            if len(reggente2.regent_prestige.all())>1:
                list_ra=[]
                for a in reggente2.regent_prestige.all():
                    ra=get_r_a(reggente1, a.affiliazione)
                    list_ra.append(ra)
                rr.conoscenza=get_rr_from_list_ra(
                    reggente1, list_ra).conoscenza
            return rr

def get_r_a(reg, aff):
    try:
        ra=regent.Regent_Affiliation.objects.get(reggente=reg, 
            affiliazione=aff)
        return ra
    except:
        fa=reg.first_affiliation().affiliazione
        faa=get_a_a(fa, aff)
        ra=regent.Regent_Affiliation(reggente=reg, affiliazione=aff, 
            conoscenza=faa.conoscenza, rapporto=faa.rapporto)
        if len(reg.regent_prestige.all())>1:
            list_aa=[]
            for a in reg.regent_prestige.all():
                aa=get_a_a(a.affiliazione, aff)
                list_aa.append(aa)
            #print(list_aa)
            ra.conoscenza=get_ra_from_list_aa(reg, list_aa).conoscenza
        return ra


def get_rr_from_list_ra(reg, list_ra):
    c=campaign.Conoscenza(name='Sconosciuto')
    r=campaign.Confidence(name='Indifferente')
    rr=regent.Regent_Relation(regent1=reg, conoscenza=c, rapporto=r)
    for x in ['Approfondita', 'Superficiale', 'Generale']:
        for y in range(len(list_ra)):
            if list_ra[y].conoscenza.name == x:
                rr.conoscenza=list_ra[y].conoscenza
                return rr
    return rr

The user choose a couple of field and the app generate a table looking for relations between tipo_primo (or primo_elemento but that is just a value so is fast) and tipo_secondo. This relations are stored like manytomany field in the model.

I don't have all the relations because that will be too long to write so in the get_r_r (the longer) before I look if exist the direct relation, if not I look for the reverse (in this case it is symmetric), if not I look for the relation between the 'groups' and if that don't exist I use the default.

Edit:

My models:

#campaign.py


class Conoscenza(models.Model):
    name = models.CharField(max_length=32, unique=True)

    def __str__(self):
        return self.name


class Confidence(models.Model):
    name = models.CharField(max_length=16, unique=True)
   ... #4 more fields



#regent.py


class BaseRegent(models.Model):
    name = models.CharField(max_length=32)
    slug = models.SlugField(primary_key=True)
    ... # 17 more fields


class Regent(Regent_PG, Regent_PNG, BaseRegent):
    affiliations = models.ManyToManyField(affiliation.Affiliation, 
        related_name='affiliation_regent', through='Prestige')
    regent_affiliations = models.ManyToManyField('self', 
        related_name='reg_aff', symmetrical=False, 
        through='Regent_Affiliation')
    regent_relations = models.ManyToManyField('self', related_name='reg_reg',
        symmetrical=False, through='Regent_Relation')
    regent_exes = models.ManyToManyField(exe.Exe, related_name='reg_exe',
        symmetrical=False, through='Regent_Exe')


class Regent_Relation(models.Model):
    regent1 = models.ForeignKey(Regent, null=True, on_delete=models.CASCADE, 
        related_name='regent1_relation')
    regent2 = models.ForeignKey(Regent, null=True, on_delete=models.CASCADE, 
        related_name='regent2_relation')
    conoscenza = models.ForeignKey(campaign.Conoscenza, to_field='name',
        on_delete=models.PROTECT, default = 'Superficiale',
        related_name='conoscenza_reggenti')
    rapporto = models.ForeignKey(campaign.Confidence, to_field='name',
        on_delete=models.PROTECT, default = 'Indifferente', 
        related_name='rapporto_regents')

    class Meta:
        unique_together = ('regent1', 'regent2')
        ordering = ['regent1', 'regent2']

    def __str__(self):
        return '%s %s' % (self.regent1, self.regent2)

Here how the view works:

1) It take the ajax request and read tipo_primo and tipo_secondo (lets suppose primo_elemento=''). They can be s = schieramento (translation: large group), a = affiliation, r = regent. Each regent belong to one or more affiliations, each affiliation belong to one schieramento. Each schieramento have more affiliations.

2) It take all the values of Conoscenza (translation: knowledge) and Confidence and make two lists useful in javascript

3) It controls in which combination between tipo_primo and tipo_secondo we are. Let's suppose they both are 'r' (it's the longer case). It means the user wants to know the relations between regents (who know who and who is enemy of who).

4) It take all (because primo_elemento == '') regent elements and put in primi. Then take all regent elements again and put in secondi, because tipo_primo and tipo_secondo are both 'r'.

5) I iterate primo and secondo to retrive the relations stored (in our case) in regent.Regent_Relation. To do so I have an external function services.get_r_r whose working I already explained here above. This is the SLOW part. Many iterations and each one slow, so get_r_r is slow

6) so I build lista_primo, lista_conoscenze, lista_rapporti. They are list of name (string) not of instance (lighter to pass, I think)

7) I build lista_secondo (again I just transform a list of instance in a list of string)

8) I pass back to javascript this list so I can print the table:

table final

\$\endgroup\$
  • \$\begingroup\$ Can you include your models and a brief description of what this is actually supposed to be doing? \$\endgroup\$ – Kevin Brown Jan 26 '17 at 6:23
  • \$\begingroup\$ Sir, you should think of using English in your code. The code is poorly written but Italian language in variable names is making it even worse for understanding. If you still not sure which part of your code is making troubles, please use any kind of Profilers to get this. \$\endgroup\$ – Alex Jan 26 '17 at 10:32
  • \$\begingroup\$ @Alex sorry about poor quality of code, I'm learning. I will use english for my new variables but I can't change the existent ones in my code and I'm not sure it will be useful to change the name in this post (I can forgot something, etc). I know which part is making problem: part 5) above \$\endgroup\$ – fabio Jan 26 '17 at 10:58
  • \$\begingroup\$ @Kevin Brown added code. \$\endgroup\$ – fabio Jan 26 '17 at 10:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.