Django-fr

Forum

#1 06-08-2015 13:32:37

loh
Membre
Inscription : 06-08-2015
Messages : 3

Optimisation de modèle

Bonjour,

je débute avec django et après avoir passé pas mal de temps à trouver une solution et à lire de la doc, je viens demander un coup de pousse à plus aguerri que moi...
Mon problème concerne la récupération de données avec le modèle que je possède et l'optimisation des traitements.

Mon problème :
J'ai une liste d'identifiants (specific_id) et je dois récupérer les produits correspondants (dans le même ordre) et charger toutes les données relatives aux répertoires, plateformes et capteurs.
Dans le but d'afficher cela.

Mon modèle :

class Product(models.Model):
    specific_id = models.CharField(max_length=100, unique=True, blank=False, null=False)
    shortname = models.CharField(max_length=100, unique=False, blank=True, null=False)

class Repository(models.Model):
    product = models.ForeignKey(Product, blank=True, null=True)
    name = models.CharField(max_length=200, unique=True, blank=False, null=False)
    url = models.CharField(max_length=2048, blank=True, null=True)

class SourceContribToProduct(models.Model):
    source = models.ForeignKey(Source)
    product = models.ForeignKey(Product)

class Source(models.Model):
    products = models.ManyToManyField(Product, through='SourceContribToProduct')
    shortname = models.CharField(max_length=100, unique=True, blank=False, null=False)
    platform = models.ForeignKey(Platform, blank=True, null=True)
    sensor = models.ForeignKey(Sensor, blank=True, null=True)

class Sensor(models.Model):
    shortname = models.CharField(max_length=50, unique=True, blank=False, null=False)
    type = models.TextField(blank=True, null=True)

class Platform(models.Model):
    shortname = models.CharField(max_length=50, unique=True, blank=False, null=False)
    description = models.TextField(blank=True, null=True)

Ma solution :

ids = [1, 2, 3, 'AZT_TY', 'SGT_YY']
# Retrive list of objects
products = Product.objects.filter(specific_id__in=ids).prefetch_related('repository_set', 'source_set')
for p in products:
    p.repositories = p.repository_set.all()
    p.sources = Source.objects.filter(sourcecontribtoproduct__product_id=p.id).select_related('sensor_set', 'platform_set')
    for s in p.sources:
        s.sensor
        s.platform

# Sort the list
products = list(products)
products.sort(key=lambda t: ids.index(t.specific_id))

Mes questions :

Voilà ce que j'ai fait, mais je trouve cela lent.
Que pensez-vous de ce code ? Comment pourrais-je l'optimiser ?
Je n'ai que 194 objets (pas plus de 5 repertoires par objet et pas plus de 3 sources par objets) et cela me prend presque 5 secondes !
Existe-t-il un moyen simple de dire de charger tous les éléments des sets sur plusieurs niveau ?

Merci d'avoir pris le temps de me lire big_smile
Bonne journée

Hors ligne

#2 10-08-2015 14:47:37

Xavier Ordoquy
Administrateur
Lieu : Puteaux, France
Inscription : 12-10-2011
Messages : 312
Site Web

Re : Optimisation de modèle

A priori, tu pourrais charger toutes tes sources en utilisant un __in = ids dans le filter et donc éviter de boucler sur les produits.

Hors ligne

#3 12-08-2015 10:21:34

loh
Membre
Inscription : 06-08-2015
Messages : 3

Re : Optimisation de modèle

J'ai trouvé la réponse à ma question, je n'ai pas besoin d'itérer sur les objets pour les charger dans view.py. Simplement besoin de créer une querySet et d'accéder dans ma template aux éléments chargés dans les _set. Dans view.py :

`products=Product.objects.filter(specific_id__in=ids).prefetch_related('repository_set', 'source_set').select_related('repository_set', 'source_set')`

Dans ma template, itérer sur :

{% for src in product.source_set.all %}
       {{src.platform.shortname}} / {{src.sensor.shortname}}<br/>
    {% endfor %}
            
    {% for repo in product.repository_set.all %}
       {{repo.url}}
    {% endfor %}

Et c'est tout...

Hors ligne

#4 12-08-2015 10:22:23

loh
Membre
Inscription : 06-08-2015
Messages : 3

Re : Optimisation de modèle

Xavier Ordoquy a écrit :

A priori, tu pourrais charger toutes tes sources en utilisant un __in = ids dans le filter et donc éviter de boucler sur les produits.

Merci pour ton indication Xavier

Hors ligne

Pied de page des forums