2013-06-17 2 views
4

J'applique le signal post_save pour appliquer des droits utilisateur par objet, puis filtre le queryset en conséquence.post_save signal et relations

Mon modèle est comme ceci:

class Project(models.Model): 
    # Relations with other entities. 
    employees = models.ManyToManyField('staff.Person', through='project.PersonProjectMembership', 
             related_name='projects') 
    research_groups = models.ManyToManyField('group.Group', related_name='projects', 
              through='project.ProjectGroupMembership') 
    departments = models.ManyToManyField('department.Department', related_name='projects', 
             through='project.ProjectDepartmentMembership') 

Le problème est le suivant: quand je prends le signal post-enregistrement, bien que je suis entré des valeurs pour les ministères, research_groups & employés, ils semblent toujours être vides. Y a-t-il quelque chose que j'ai manqué?

Mise à jour: Sous le code actuel, qui ne fonctionne pas encore comme prévu. J'ai changé le post_save par m2m_changed.

from django.db.models.signals import m2m_changed 
from django.db import models 
from django.dispatch.dispatcher import receiver 

class Project(models.Model): 
    employees = models.ManyToManyField('staff.Person', through='project.PersonProjectMembership', 
    related_name='projects') 

class PersonProjectMembership(models.Model): 
    project = models.ForeignKey('project.Project', related_name="person_memberships") 
    person = models.ForeignKey('staff.Person', related_name="project_memberships") 
    lead = models.BooleanField(default=False) 
    position = models.CharField(max_length=50) 
    project_manager = models.BooleanField(
     default=False 
    ) 

    class Meta: 
     permissions = (
      ('view_personprojectmembership', _('View person project membership')), 
     ) 

@receiver(m2m_changed, sender=Project.employees.through) 
def _on_save_project_assign_privileges(sender, instance, action, reverse, model, pk_set, using, **kwargs): 
    # [...] 

SOLUTION

Dans mon modèle de projet, je suis en train de définir explicitement PersonProjectMembership comme modèle intermédiaire dans les employés de relation m2m:

class Project(models.Model): 
    # Relations with other entities. 
    employees = models.ManyToManyField('staff.Person', through='project.PersonProjectMembership', related_name='projects') 

Le calendrier quand j'enregistre un projet, est la suivante:

  1. Project.save()
  2. PersonProjectMembership.save()

Il est donc normal que, sur Project.post_save, les employés soient toujours vides. Ce que je devais faire était en écoutant le signal post_save de PersonProjectMembership:

@receiver(post_save, sender=PersonProjectMembership) 
def my_listener(**kwargs): 
    # do stuff [...] 

Regardez dans https://docs.djangoproject.com/en/1.9/ref/models/fields/#django.db.models.ManyToManyField.through et https://docs.djangoproject.com/en/1.9/topics/signals/

+0

appelez-vous 'save_m2m()'? https: //docs.djangoproject.com/fr/dev/themes/forms/modelforms/# la méthode save-save Si cela ne résout pas, pouvez-vous montrer la vue où vous enregistrez? – karthikr

+0

salut karthikr, merci pour votre réponse. Je sauve de l'admin de Django. Donc, cela ne devrait pas être le problème, je pense: -/ – sogeking

+0

pouvez-vous montrer la méthode post_signal? – lalo

Répondre

1

Après avoir creusé beaucoup sur mon code, et de faire des tests simples, j'ai essayé le signal m2m_changed comme suggéré Krasnoperov. J'ai réalisé que ce signal ne fonctionne pas bien si vous déclarez explicitement un modèle "through", "PersonProjectMembership" dans mon cas.

Puis j'ai repensé et lié ma méthode au signal post_save de "PersonProjectMembership". Cela fonctionne parfaitement.

1

Comme vous le savez, les relations many2many sont stockées par table supplémentaire, qui contient les clés primaires des deux extrémités relation. À cause de cela, les économies d'instance de modèle par rapport Many2Many il est procédé en deux étapes:

  1. Dans un premier temps, par exemple est enregistrer: nouvel enregistrement dans la base de données est créée et l'instance reçoit est la clé primaire. post_save est renvoyé en ce moment. Ensuite, les relations sont sauvegardées: les enregistrements dans la table de relations sont créés. m2m-changed le signal est déclenché à ce moment.

En d'autres termes, lorsque post_save est tiré, les relations m2m ne sont pas traitées encore.

Vous pouvez consulter la documentation: m2m-changed

+0

Merci krasnoperov, mais cela ne semble pas fonctionner @receiver (m2m_changed, sender = Project.employees.through) def _on_save_project_assign_privileges (expéditeur, instance, action, reverse, modèle, pk_set, en utilisant, ** kwargs): – sogeking

Questions connexes