6

私は次のモデルを持っています:

class Item(models.Model):
    # fields
    # ...

class Collection(models.Model):
    items = models.ManyToManyField(Item, related_name="collections")
    # other fields
    # ...

今、私は2つのことが欲しいです:

  1. Itemをに追加できるかどうかを制御したいCollection
  2. が追加または削除されたCollection場合に、そのフィールドの一部を更新する必要があります。Item

django.db.models.signals.m2m_changed2番目の問題については、関係の変更にフックするために使用できる があることを知っています。Collectionシグナルコールバック内で変更することは許可されていますか? 問題1の挿入を「中止」するためにも信号を使用できますか?

4

2 に答える 2

8

両方の目的の動作にアプローチする最良の方法は、シグナルを使用するのではなくthrough、引数を使用して明示的に定義するテーブルでオーバーライドされた save() および delete() メソッドを使用することだと思いますthrough: https://docs.djangoprojectを参照してください。 .com/en/dev/ref/models/fields/#django.db.models.ManyToManyField.through . そしてこれ: https://docs.djangoproject.com/en/dev/topics/db/models/#overriding-predefined-model-methods

このようなもの:

# -*- coding: utf-8 -*-

from django.db import models


class Item(models.Model):
    # fields
    # ...

class Collection(models.Model):
    items = models.ManyToManyField(Item, related_name="collections", through="CollectionItem")
    # other fields
    # ...

class CollectionItem(models.Model):
    collection = models.ForeignKey(Collection)
    item = models.ForeignKey(Item)

    def save(self, *args, **kwargs):
        # Only allow this relationship to be created on some_condition
        # Part 1 of your question.
        if some_condition:
            super(CollectionItem, self).save(*args, **kwargs)

            # Update some fields on Collection when this
            # relationship is created
            # Part 2 of your question (1/2)
            self.Collection.updateSomeFields()

    def delete(self, *args, **kwargs):
        collection = self.collection
        super(CollectionItem, self).delete(*args, **kwargs)

        # Update some fields on Collection when this relationship
        # is destroyed.
        # Part 2 of your question (2/2)
        collection.updateSomeFields()

ちなみに、リレーションシップを追加すると、このスルー モデルで保存シグナル発生することがわかります。

また、シグナルに関しては、スルー テーブルを配置すると、pre_save および/または post_save シグナルをリッスンできますが、どちらもリレーションシップの作成を直接拒否することはできません。

モデルの 1 つまたは両方がサードパーティから提供されていて、実際にスルー テーブルを作成できない場合は、信号ルートが唯一の方法である可能性があります。

https://docs.djangoproject.com/en/dev/ref/signals/#m2m-changed

その場合、 m2m_changed イベントをリッスンして、コレクション オブジェクトの更新をトリガーし (質問のパート 2)、不適切に作成された関係をさかのぼって削除できます (質問のパート 1)。ただし、この後者のビットは厄介なので、できれば明示的なスルー テーブルを使い続けたいと思います。

于 2013-05-28T19:13:54.473 に答える