2015-08-29 2 views
3

Il y a deux parties de cette question pour la situation suivante:auto-créer des instances de modèles intermédiaires django pour une nouvelle instance créée dans le modèle de terrain foreignkey

Je vais utiliser par exemple pour décrire la question:

Ce sont mes modèles django:

class Zone(models.Model): 
    zone_name = models.CharField(max_length = 10) 
    zone_number = models.CharField(max_length = 10) 

    class Meta: 
     ordering = ('zone_name',)  

    def __unicode__(self): 
     return self.zone_name 


class Stage(models.Model): 
    stage_number = models.CharField(max_length = 10) 
    stage_name = models.CharField(max_length = 10) 
    zones = models.ManyToManyField(Zone, through='ZoneStage') 

    class Meta: 
     ordering = ('stage_number',)  

    def __unicode__(self): 
     return self.stage_number 

    @property 
    def value(self): 
     return ZoneSubStage.objects.filter(substage__stage=self).aggregate(Sum('value')).get('value__sum', 0) 


class ZoneStage(models.Model): 
    zone = models.ForeignKey(Zone) 
    stage = models.ForeignKey(Stage) 
    value = models.PositiveSmallIntegerField(default=0) 

    class Meta: 
     ordering = ('zone',)   

    def __unicode__(self): 
     return '%s %s' % (self.zone, self.stage) 

class SubStage(models.Model): 
    sub_name = models.CharField(max_length=10) 
    stage = models.ForeignKey(Stage) 
    zones = models.ManyToManyField(Zone, through='ZoneSubStage') 

    def __unicode__(self): 
     return self.sub_name 


class ZoneSubStage(models.Model): 
    zone = models.ForeignKey(Zone) 
    substage = models.ForeignKey(SubStage) 
    value = models.PositiveSmallIntegerField(default=0) 

    def __str__(self): 
     return '%s %s' % (self.zone, self.substage) 

QUESTION 1: Comment créer automatiquement de nouvelles instances de ZoneStage pour tous rel Stades si je crée manuellement une nouvelle instance de zone?

par exemple. J'ai les instances de Stage suivantes: S1, S2, S3, S4 et je crée une nouvelle instance de zone "A". Donc, je veux créer automatiquement de nouvelles instances de ZoneStage AS1, AS2, AS3, AS4 SI une telle instance n'existe pas déjà?

QUESTION 2: Ceci est l'extension à la question n ° 1. Si je crée une nouvelle zone que je veux créer des instances automatiquement ZoneStage comme décrit à la question 1 plus je veux créer des instances automatiquement ZoneSubStage pour tous à toutes les étapes sous-étapes si cette instance ZoneSubStage n'existe pas déjà.

Je ne sais pas par où commencer. Je pense que je devrais peut-être lire d'abord sur post_save()?

Répondre

0

Sous-réponse: Premièrement vous ne voulez pas ajouter zone = models.ForeignKey(Zone) dans la classe ZoneStage parce que vous avez cette information avec stage = models.ForeignKey(Stage);

Question 1: vous pouvez intercepter le signal (post_save) après avoir créé l'étape comme ceci.

@receiver(post_save, sender=Stage) 
def gen_coupon(sender, instance, raw=True, **kwargs): 
    new_zone_stage = ZoneStage(stage=instance) 
    new_zone_stage.save() 
    return kwargs 

Question 2: Même logique, mais vous changez l'expéditeur à l'objet modèle courant créé

+0

Je ne comprends pas votre commentaire sur le champ de zone qui n'est pas nécessaire dans ZoneStage. Si je l'enlève, je supprimerai la relation avec ma zone. L'étape du modèle est liée à la zone du modèle via le modèle intermédiaire ZoneStage via la zone de champ.Modèle ZoneStage contient l'étape de terrain qui est le modèle FK à l'étape. Le modèle ZoneStage contient une zone de champ qui correspond au modèle FK à zone. Cela signifie que mon modèle ZoneStage est au milieu entre Zone et Stage et c'est la seule relation. Je ne vois aucune autre relation entre Zone et Stage que via ZoneStage. Corrigez-moi si je me trompe. – BlueTomato

+0

Jetez un oeil tout votre code je vous aide – rakwen

+1

d'abord vous avez le modèle de zone ok!
Maintenant vous ajoutez Stage Model dans ce cas pour accéder au modèle de zone avec stage vous pouvez utiliser des zones ou dans zone vous pouvez utiliser stage_set ok
maintenant dans ZoneStage vous pouvez accéder à la scène avec stage (si vous pouvez accéder au stage vous pouvez accéder à zone). – rakwen

0

J'ai lu au sujet de mon problème et a rassemblé quelques connaissances des manuels de django. Les conseils de Rakwen m'ont orienté vers la bonne direction. C'est ce que j'ai et cela fonctionne en ce moment. Bien que, je ne vérifie pas si une telle instance existe déjà. De plus, j'ai lu dans deux scoop de django qu'il n'est pas bon d'utiliser des signaux sauf si c'est vraiment vraiment nécessaire. Je devrais plutôt utiliser des gestionnaires de modèles.

J'ai créé le fichier signals.py et l'ai stocké dans mon dossier d'application à côté de models.py. Il contient le code suivant:

from django.dispatch import Signal 


def create_new_zonestage_if_new_zone(sender, **kwargs): 
    if kwargs.get('created',False): 
     from models import Stage, ZoneStage 
     stages = Stage.objects.all() 
     for mystage in stages: 
      ZoneStage.objects.get_or_create(stage=mystage,zone=kwargs.get('instance')) 
    return kwargs 

def create_new_zonesubstage_if_new_zone(sender, **kwargs): 
    if kwargs.get('created',False): 
     from models import SubStage, ZoneSubStage 
     substages = SubStage.objects.all() 
     for mysubstage in substages: 
      ZoneSubStage.objects.get_or_create(substage=mysubstage,zone=kwargs.get('instance')) 
    return kwargs 

J'ai ajouté suivant dans models.py:

ci-dessus classes de modèle:

from django.db.models.signals import post_save 
from . import signals 

ci-dessous classes de modèle:

post_save.connect(signals.create_new_zonestage_if_new_zone, sender=Zone) 
post_save.connect(signals.create_new_zonesubstage_if_new_zone, sender=Zone) 

il travaux.