2009-09-21 7 views
2

Je développe une application de portefeuille. Au sein de cette application, j'ai un modèle appelé « Projet », qui ressemble à ceci:Limitation de la portée d'une relation ForeignKey?

class Project(models.Model): 
    ... 
    images = models.ManyToManyField(Image) 
    ... 

donc, au fond, ce projet peut contenir un ensemble d'images (l'une de ces images peuvent appartenir à un autre projet aussi) . Maintenant, ce que je voudrais ajouter est une façon de spécifier qu'une de ces "images" est une "image_principale".

Je pourrais ajouter quelque chose comme ceci:

class Project(models.Model): 
    ... 
    images = models.ManyToManyField(Image, related_name='images') 
    lead_image = models.ForeignKey(Image, related_name='lead_image') 
    ... 

Cependant, le problème est que dans ce cas, lead_image peut être toute image. Ce que je veux vraiment, c'est que ce soit l'une des "images" qui appartiennent à cette instance de modèle. Je pense que j'ai besoin d'utiliser l'argument "ForeignKey.limit_choices_to", mais je ne suis pas sûr de savoir comment l'utiliser ... d'autant plus que quand l'instance du modèle est créée, il n'y en aura pas encore images dans le répertoire "images".

Toute aide serait grandement appréciée.

Doug

Répondre

2

Une autre approche à votre problème est d'utiliser une table intermédiaire avec une propriété booléenne « de is_lead_image ».

class Image(models.Model): 
    ... 

class Project(models.Model): 
    images = models.ManyToManyField(Image, through='ProjectImage') 
    ... 

class ProjectImage(models.Model): 
    image = models.ForeignKey(Image) 
    project = models.ForeignKey(Project) 
    is_lead_image = models.Boolean(default=False) 

    def save(self, *args, **kwargs): 
     if self.is_lead_image: 
      self._default_manager.filter(project=self.project).update(is_lead_image=False) 
     return super(ProjectImage, self).save(*args, **kwargs) 

* Note: Si vous le souhaitez et si vous avez accès, vous pouvez également ajouter simplement le champ is_lead_image et la sauvegarde directement à la classe Image.

+0

Intéressant. Je vais essayer ça. –

2

Si vous souhaitez obtenir l'effet de limitation dans l'outil d'administration, vous pouvez remplacer la méthode formfield-for-foreignkey et insérer votre propre filtre.

class ProjectAdmin(admin.ModelAdmin): 

    # ... 

    def formfield_for_foreignkey(self, db_field, request, **kwargs): 
     if db_field.name == "lead_image": 
      kwargs["queryset"] = self.model.images.all() 
      return db_field.formfield(**kwargs) 
     return super(ProjectAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs) 

Le problème que je vois ici (avec cette idée générale que la cueillette d'images cueillies) est que pour les nouveaux modèles, d'abord model.images ne seront pas réglées lorsque la page se charge. Vous allez probablement faire face à ce problème, peu importe ce que vous faites avec le côté serveur.

Cela pourrait fonctionner, mais cela nécessite un clic supplémentaire: Lorsque le modèle est créé, les images du modèle ManyToMany seront sélectionnées. Après avoir sélectionné, si vous cliquez sur "Enregistrer et continuer", ces images doivent apparaître dans le champ FK model.lead-image. Votre autre option serait de remplacer le formulaire d'administration par défaut et de créer quelque chose de personnalisé (personnalisé comme dans javascript fancy-pants personnalisé pour mettre à jour automatiquement la zone de liste déroulante «image principale»).

+1

Merci. Cela semble être un bon moyen d'aller. Je ne pense pas qu'il existe une solution "idéale" pour cela. –

Questions connexes