2009-10-07 3 views
3

J'ai un modèle où les tâches sont des travaux que chacun peut faire en fonction d'un certain nombre d'autres tâches à accomplir avant de pouvoir démarrer. Les tâches sont regroupées en tâches et je souhaite interdire les dépendances entre les tâches. Tel est le sous-ensemble pertinent de mon modèle:Django: appliquer la contrainte "same parent" à ManyToManyField mappage à self

class Job(models.Model): 
    name = models.CharField(max_length=60, unique=True) 

class Task(models.Model): 
    job = models.ForeignKey(Job) 
    prerequisites = models.ManyToManyField(
     'self', 
     symmetrical=False, 
     related_name="dependents", 
     blank=True) 

Est-il possible que je peux exprimer la contrainte que toutes les tâches préalables doivent avoir le même emploi? I pourrait appliquer cela au niveau de la vue, mais je voudrais vraiment le faire fonctionner au niveau du modèle afin que l'interface d'administration affichera les options appropriées lors du choix des conditions préalables pour une tâche. Je pensais pouvoir utiliser "limit_choices_to", mais en y regardant de plus près, il semble qu'il faille une requête statique, et non quelque chose qui dépend des valeurs de cet objet de tâche.

Répondre

3

Il existe deux problèmes distincts ici. Si vous souhaitez appliquer cette contrainte au niveau du modèle, vous devrez peut-être définir un modèle "through" explicite et remplacer sa méthode save() (vous ne pouvez pas simplement remplacer Task.save() par "is" t nécessairement invoqué pour ajouter des entrées à un M2M). Django 1.2 aura un framework de validation de modèle plus complet, plus proche de la validation de formulaire.

Si vous souhaitez que certains choix apparaissent dans l'administrateur, il s'agit d'un problème de niveau formulaire. Vous pouvez définir dynamiquement l'attribut queryset du ModelMultipleChoiceField dans méthode init d'un formulaire:

class TaskForm(forms.ModelForm): 
    class Meta: 
     model = Task 

    def __init__(self, *args, **kwargs): 
     super(TaskForm, self).__init__(*args, **kwargs) 
     self.fields['prerequisites'].queryset = Task.objects.filter(job=self.instance.job) 

Vous devrez peut-être introduire quelques vérifications supplémentaires ici pour traiter le cas de la création d'un nouveau groupe (dans ce cas, « l'auto. instance.job "sera probablement None); L'ensemble des prérequis disponibles que vous souhaitez n'est pas clairement défini, car une nouvelle tâche n'a pas encore de travail.

+0

La méthode save de la tâche est-elle invoquée lors de la création d'une relation many-to-many? J'ai supposé que parce qu'il avait sa propre table en coulisses, cela n'impliquerait pas task.save(). Je pense que la solution de niveau formulaire est ce dont j'ai besoin pour le moment. Je n'ai pas encore examiné les formulaires, mais je vais essayer quand j'aurai l'occasion de revenir et accepter cette réponse si cela fonctionne. – Weeble

+0

Ah, vous avez raison de dire que save() ne convient pas dans le cas d'un champ M2M. Il y aurait un moyen de le faire, mais cela pourrait nécessiter la définition d'un modèle explicite "through" et la substitution de sa méthode save(). Je vais modifier cette partie de ma réponse. –

Questions connexes