복붙노트

[PYTHON] 장고 manytomany 신호? [복제]

PYTHON

장고 manytomany 신호? [복제]

그런 모델이 있다고 가정 해 봅시다.

class Event(models.Model)
    users_count = models.IntegerField(default=0)
    users = models.ManyToManyField(User)

이벤트가 일부 사용자를 추가 / 삭제하면 users_count 값을 업데이트하는 것이 어떻습니까?

해결법

  1. ==============================

    1.가능하다면 이벤트 및 사용자에 참여할 수있는 참여 모델을 소개 할 수 있습니다.

    가능하다면 이벤트 및 사용자에 참여할 수있는 참여 모델을 소개 할 수 있습니다.

    class Participation(models.Model):
        user = models.ForeignKey(User)
        event = models.ForeignKey(Event)
    
    class Event(models.Model):
        users = models.ManyToManyField(User, through='Participation')
    

    Participation에서 보낸 pre_save 신호를 처리하여 instance.event 개수를 업데이트합니다. m2m의 처리를 단순화합니다. 그리고 대부분의 경우, 일부 논리 및 데이터가 중간 모델에서 가장 적합하다는 것이 나중에 밝혀졌습니다. 그런 경우가 아니라면 맞춤 솔루션을 사용해보십시오 (어쨌든 이벤트에 사용자를 추가하는 코드 경로가 많아서는 안됩니다).

  2. ==============================

    2.나는 내장 된 신호 django.db.models.signals.m2m_changed를 사용하여 문제를 해결했다.

    나는 내장 된 신호 django.db.models.signals.m2m_changed를 사용하여 문제를 해결했다.

    제 경우에는 ManyToMany가 변경 될 때마다 다른 모델의 관련 인스턴스를 업데이트해야합니다. 아시다시피 Model.save ()를 재정 의하여 작동하지 않습니다.

    여기 내 (프랑스어 및 간체) 모델 :

    class BaseSupport(EuidModel):
        nom = models.CharField(max_length=100, blank=True)
        periodicite = models.CharField('périodicité', max_length=16,
                                       choices=PERIODICITE_CHOICES)
        jours_de_parution_semaine = models.ManyToManyField('JourDeLaSemaine', blank=True)
    
        class Meta:
            abstract = True
    
    
    class Support(BaseSupport):
        pass
    
        def save(self, *args, **kwargs):
            create_cahier_principal = False
            if not self.pk:
                create_cahier_principal = True
            super(Support, self).save(*args, **kwargs) 
            if create_cahier_principal:
                c = Cahier.objects.create(support=self,ordre=1, numero=1,
                                          nom=self.nom, nom_court=self.nom_court,
                                          euid=self.euid, periodicite=self.periodicite)
    
    
    
    class Cahier(BaseSupport):
        """Ex : Cahier Saumon du Figaro Quotidien."""
        support = models.ForeignKey('Support', related_name='cahiers')
        ordre = models.PositiveSmallIntegerField()
        numero = models.PositiveSmallIntegerField(u'numéro', null=True, blank=True)
    
    
    def sync_m2m_cahier_principal(sender, **kwargs):
        if kwargs['action'] not in ('post_add', 'post_clear', 'post_remove'):
            return
        support = kwargs['instance']
        cahier_principal = support.cahiers.get(euid=support.euid)
        cahier_principal.jours_de_parution_semaine.clear()
        if kwargs['action'] == 'post_clear':
            return 
        for jour in support.jours_de_parution_semaine.all():
            cahier_principal.jours_de_parution_semaine.add(jour)
    m2m_changed.connect(sync_m2m_cahier_principal,
                        sender=Support.jours_de_parution_semaine.through)
    

    어쩌면이 해결책은 이상적이지만 나는 원숭이 패치 장고가 싫어!

  3. ==============================

    3.M2M에 대한 업데이트가 원자 적이지 않고 이벤트 인스턴스를 저장 한 후에 발생하므로 save ()를 무시하는 것이 도움이되지 않을 것입니다. delete () 의미론을 연구하지는 않았지만 아마도 비슷할 것입니다. 이것은 다른 스레드에서 논의되었습니다.

    M2M에 대한 업데이트가 원자 적이지 않고 이벤트 인스턴스를 저장 한 후에 발생하므로 save ()를 무시하는 것이 도움이되지 않을 것입니다. delete () 의미론을 연구하지는 않았지만 아마도 비슷할 것입니다. 이것은 다른 스레드에서 논의되었습니다.

    사람들은이 문제에 대해 이야기하고 있습니다. 지금까지 본 가장 좋은 해결책은 gregoirecachet가 작성한 MonkeyPatch입니다. 이것이 1.2로 만들 것인지 아닌지 나는 모른다. 릴리스 관리자 (James Bennett)가 사람들이 동결 날짜를 지키려고 시도한 이후로 (아마도 방금 전달 된 주요 일정).

  4. ==============================

    4.이를위한 "디자인 패턴"이 있습니다.

    이를위한 "디자인 패턴"이 있습니다.

    꽤 많이 save () 및 delete ()를 재정의하십시오.

    그들이 말했듯이 리스너를 사용하는 것도 옵션이지만,이 시나리오에서는 오버라이드 메커니즘을 더 좋아하는 경향이 있습니다.

  5. from https://stackoverflow.com/questions/1958540/django-manytomany-signals by cc-by-sa and MIT license