5

私がそのようなモデルを持っているとしましょう

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

イベントによって一部のユーザーが追加/削除された場合、users_count の値をどのように更新することをお勧めしますか?

4

3 に答える 3

8

あなたの場合、可能であれば、Participationイベントとユーザーを結合するモデルを導入できます:

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 の処理が大幅に簡素化されます。そしてほとんどの場合、一部のロジックとデータが中間モデルに最適であることが後で判明します。それが当てはまらない場合は、カスタム ソリューションを試してください (ユーザーをイベントに追加する多くのコード パスは必要ありません)。

于 2009-12-24T22:26:28.630 に答える
4

組み込みシグナル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)

たぶん、この解決策は理想とはかけ離れていますが、私は Django にモンキー パッチを適用するのは嫌いです。

于 2011-05-18T16:02:47.100 に答える
2

M2M への更新はアトミックではなく、Event インスタンスの保存後に発生するため、save() をオーバーライドしても役に立たない可能性があります (delete() セマンティクスについては調べていませんが、おそらく似ています)。これは別のスレッドで議論されました。

人々はこの問題について話し、取り組んでいます。私がこれまで見てきた最善の解決策は、gregoirecachet によるこの MonkeyPatch です。これが1.2になるかどうかはわかりません。おそらく、リリース マネージャー (James Bennett) が凍結日 (重要な日付が過ぎたばかり) を尊重するように人々を誘導しようとしているため、そうではありません。

于 2009-12-24T15:57:10.100 に答える