2012-03-12 2 views
0

Je crée une liste de tâches dans django. J'ai un modèle avec quelques propriétés:Calculs de champs dynamiques dans Django

class Action(models.Model): 
    name = models.CharField("Action Name", max_length=200, unique = True) 
    slug = models.SlugField(max_length=100, blank=True) 

    complete = models.BooleanField(default=False, verbose_name="Complete?") 

    effort = models.IntegerField("Effort Level", choices = LEVELS, default = 3) 
    importance = models.IntegerField("Importance", choices = LEVELS, default = 3) 
    enjoyment = models.IntegerField("Enjoyment", choices = LEVELS, default = 3) 

    days_to_expiration = models.IntegerField("Days to Expiration", choices = DAYS_TO_EXPIRATION, default = 7) 

    reset_date = models.DateField("Date of Action Reset", blank=True, null=True) 

Je veux trier en fonction de la priorité. Je définis la priorité en tant que:

priority = (1 + (today's date - reset_date)/days_to_expiration) * importance 

Ceci augmente simplement l'importance en fonction de la «date d'échéance» de la tâche.

Maintenant, quand je tire une liste d'actions incomplètes, je peux calculer ce numéro de priorité pour chaque élément d'action, mais cela ne semble pas efficace puisque je finirai par calculer plusieurs fois les mêmes nombres. Je pourrais définir un nouveau champ dans le modèle:

priority = models.DecimalField("Priority", max_digits=4, decimal_places=2, blank = True, null = True) 

et programmer une fonction à exécuter une fois par jour pour calculer la nouvelle priorité par tâche.

Mais je veux savoir s'il est possible de programmer le calcul de priorité directement dans le modèle. Ainsi, le champ prioritaire dans le modèle Action est nécessairement, par conception, une fonction d'importance et de days_to_expiration. Il serait mis à jour dynamiquement en utilisant les valeurs d'importance, days_to_expiration, et la date d'aujourd'hui. De cette façon, la priorité serait toujours calculée automatiquement quand j'en ai besoin. Est-ce une possibilité?

Répondre

1

Vous pouvez faire quelque chose comme:

class MyModel(models.Model): 
    ... 
    @property 
    def priority(self): 
     return (1 + (date.today() - self.reset_date)/self.days_to_expiration) * self.importance 

Ensuite, vous pouvez y accéder comme tout autre attribut sur votre modèle

priority = my_model.priority 
+0

Je ne pense pas que cela résout vraiment le problème; vous continuez de calculer 'priorité' à chaque fois. –

+0

Cela semble être ce que le PO veut: "De cette façon, la priorité serait toujours calculée automatiquement quand j'en ai besoin." –

+0

Maintenant que vous le mentionnez, je vois le point d'isbadawi que cela équivaudrait à la même chose: la priorité sera calculée plusieurs fois si ce n'est pas strictement nécessaire. Mais c'était l'idée que je pensais. –

2

Ce que vous voulez est appelé denormalization; priority est un champ dénormalisé. Vous pouvez probablement pirater avec des signaux, ou étendre les méthodes save, ou peut-être utiliser des méthodes de gestion d'une manière intelligente pour y parvenir, mais une bonne alternative est d'utiliser django-denorm. Le tutoriel passe par une situation très similaire à la vôtre.

+0

ce qui est vraiment intéressant. Je me demande si django-denorm peut créer une dépendance à la date? Donc, lorsque la date change, le champ prioritaire est-il également mis à jour? –

+0

@Ed. Vous pouvez le configurer pour qu'il soit mis à jour tous les jours, si c'est ce que vous demandez. Voir l'exemple avec le démon à la fin –

Questions connexes