2009-03-06 7 views
0

J'écris un système de sauvegarde en Python, avec un frontal Django. J'ai décidé d'implémenter la planification d'une manière un peu étrange - le client interrogera le serveur (toutes les 10 minutes environ), pour une liste des sauvegardes qui ont besoin de faire. Le serveur ne répond que lorsque l'heure de la sauvegarde est atteinte. C'est de garder la plate-forme du système indépendant - de sorte que je ne compte pas sur cronjobs ou similaires. Par conséquent, le frontal Django (qui expose une API XML-RPC) doit stocker la planification dans une base de données et interpréter cette planification pour décider si un client doit démarrer ou non.Quelle est la meilleure façon de représenter une planification dans une base de données, via Python/Django?

Actuellement, le planning est stocké en utilisant 3 champs: jours, heures et minutes. Ce sont des listes d'entiers séparés par des virgules, représentant les jours de la semaine (0-6), les heures du jour (0-23) et les minutes de l'heure (0-59). Décider si un client doit commencer à sauvegarder ou non est une opération horriblement inefficace - Python doit boucler tous les jours depuis 7 jours dans le passé, puis les heures, puis les minutes. J'ai fait quelques optimisations pour m'assurer qu'il ne boucle pas trop - mais quand même!

Cela fonctionne relativement bien, bien que la mise en œuvre soit assez moche. Le problème que j'ai est comment afficher et interpréter cette information via le formulaire HTML sur le front-end. Actuellement, j'ai juste d'énormes listes de champs à sélection multiple, qui évidemment ne fonctionnent pas bien.

Quelqu'un peut-il suggérer une méthode différente pour mettre en œuvre le calendrier qui serait plus efficace, et aussi plus facile à représenter dans un formulaire HTML?

+0

Pourriez-vous clarifier un peu le scénario? Qu'est-ce qui est sauvegardé - les données sur le client? Y a-t-il une raison pour laquelle vous ne stockez pas simplement la prochaine date de sauvegarde dans la base de données en tant que datetime? –

+0

Ou l'intervalle de sauvegarde en tant que timedelta? Si vous avez sauvegardé l'heure de la dernière sauvegarde, et le timedelta requis, le calcul serait un jeu d'enfant. –

+0

Je ne sais pas pourquoi je n'y ai pas pensé. J'allais chercher une syntaxe similaire à celle d'un cron - et j'étais complètement coincé sur ce chemin. Le plan consiste maintenant à demander à l'utilisateur la prochaine date/heure d'exécution et à l'enregistrer avec le delta. Je peux alors utiliser un joli widget datepicker JQuery UI :). Merci pour votre aide! –

Répondre

3

Jetez un oeil à django-chronograph. Il a une interface assez agréable pour la planification des travaux à toutes sortes d'intervalles. Vous pourriez peut-être emprunter des idées à ce sujet. Il repose sur python-dateutil, que vous pouvez également trouver utile pour spécifier des événements récurrents.

+0

+1 pour django-chronograph, et il utilise dateutil pour fournir un langage de spécification de temps riche. –

+0

dateutil semble vraiment puissant, mais je ne pense pas que je vais l'utiliser pour ce projet pour réduire les dépendances. Avec la méthode décrite ci-dessus, je n'ai pas besoin de quelque chose de plus compliqué qu'un peu de maths! –

0

Votre question est un peu ambiguë: voulez-vous dire: "Sauvegardez tous les dimanches, lundis et vendredis à l'heure X."?

Si oui, utilisez un Bitmask pour stocker le programme récurrent comme un entier:

Disons que vous voulez une copie de sauvegarde tel que mentionné ci-dessus le dimanche, le lundi et le vendredi. Encodez les jours de la semaine comme un entier (représenté en binaire):

S M T W T F S 
1 1 0 0 0 1 0 = 98 

Pour savoir si aujourd'hui (. Par exemple vendredi) est un jour de sauvegarde, il suffit de faire une opération de bits and:

>>> 0b1100010 & 0b0000010 != 0 
True 

pour obtenir le jour courant comme un entier, vous avez besoin de compenser par un depuis weekday() prend semaine commence le lundi:

current_day = (timezone.now().weekday() + 1) % 7 

en résumé, le schéma de votre Schedule objet ressemblerait à quelque chose comme:

class Schedule(models.Model): 
    days_recurrence = models.PositiveSmallIntegerField(db_index=True) 
    time = models.TimeField() 

Avec ce schéma, vous auriez besoin d'un nouvel objet Schedule pour chaque moment de la journée que vous souhaitez sauvegarder. Il s'agit d'une recherche rapide, car l'opération au niveau du bit coûte environ 2 cycles et, étant donné que vous indexez le champ days_recurrence, la recherche de jour la plus défavorable de O(logn) devrait réduire considérablement votre complexité. Si vous souhaitez en extraire davantage de performances, vous pouvez également utiliser un masque de bits pour heure puis enregistrer la minute.

+0

Ceci est une solution très élégante. – user2660171

Questions connexes